- Inport
UnityAttributes.dllto your unity project - Disable all ckeckboxes in
UnityAttributes.dllimport settings panel. PressApply
- Add
RoslynAnalyzertag toUnityAttributes.dll
Automatically generates constructors for a class, including all non-static fields except those marked with GenConstructorIgnore .
Apply [GenConstructor] to your partial class. All non-static fields (except those marked with [GenConstructorIgnore] ) will be included as parameters in the generated constructor.
[GenConstructor]
public partial class MyClass
{
private int _value1, _value2;
public int value3;
[GenConstructorIgnore] private int _ignored;
private readonly int _readonlyValue;
}
// Usage
var obj = new MyClass(1, 2, 3, 4);Generated code
public partial class MyClass
{
public MyClass() { }
public MyClass(int value1, int value2, int value3, int readonlyValue)
{
this._value1 = value1;
this._value2 = value2;
this.value3 = value3;
this._readonlyValue = readonlyValue;
}
}Restricts assignment to the field only within Unity MonoBehaviour lifecycle methods: Awake , OnEnable , Start , or Reset . Assigning elsewhere will trigger a Roslyn analyzer error.
Apply [MonoReadonly] to a field in a MonoBehaviour. Only assign to this field in Awake , OnEnable , Start , or Reset methods.
public class MyComponent : MonoBehaviour
{
[MonoReadonly]
private int _score;
void Awake() { _score = 10; } // Allowed
void Update() { _score = 20; } // Error: not allowed
}Generates a public property accessor for a private or protected field.
Apply [PublicAccessor] to a private or protected field in a partial class. A public property will be generated for that field.
public partial class MyClass
{
[PublicAccessor] private int _value;
}
// Usage
var obj = new MyClass();
int v = obj.Value; // Accesses the private _value fieldGenerated code
public int Value => _value;Prevents assignment to the field outside of its declaration (enforced by analyzer). Useful for enforcing immutability in Unity projects.
Apply [Readonly] to a field. You can only assign to this field at its declaration.
public class MyClass
{
[Readonly]
private int _score = 10;
}
// Usage
// _score = 20; // Error: assignment not allowedGenerates a record-like class with value equality, ToString , and other utility methods, similar to C# 9 record but for older C# or Unity compatibility.
Apply [Record] to your partial class. The generator will create constructors, Equals , GetHashCode , and ToString methods.
[Record]
public partial class MyRecord
{
public int Id;
public string Name;
}
// Usage
var rec = new MyRecord(1, "Test");
Console.WriteLine(rec); // MyRecord(Id: 1, Name: Test)Generated code
public partial class MyRecord
{
public MyRecord() { }
public MyRecord(int id, string name)
{
this.Id = id;
this.Name = name;
}
public override string ToString() => $"MyRecord(Id: {Id}, Name: {Name})";
public override int GetHashCode()
{
unchecked
{
var hashCode = 0;
hashCode = (hashCode * 397) ^ Id.GetHashCode();
hashCode = (hashCode * 397) ^ (Name?.GetHashCode() ?? 0);
return hashCode;
}
}
public bool Equals(MyRecord other)
=> Id.Equals(other.Id) && Name == other.Name;
public override bool Equals(object obj)
=> obj is MyRecord other && Equals(other);
public static bool operator ==(MyRecord left, MyRecord right) => left.Equals(right);
public static bool operator !=(MyRecord left, MyRecord right) => !left.Equals(right);
}Generates static shader property IDs and helper methods for setting/getting shader properties on Unity materials, global shader properties, MaterialPropertyBlocks, or ComputeShaders. Supports multiple property types including Float, Integer, Bool, Color, Vector, Matrix, Texture, and arrays.
Apply [ShaderProperty] attributes to your partial class. Each attribute defines a shader property with a name, type, and optional mode. You can apply multiple [ShaderProperty] attributes to the same class.
Parameters:
name(string): The shader property name as it appears in the shadertype(ShaderPropertyType): The property type (Float, Integer, Bool, Color, Vector, Matrix, Texture, Buffer, ConstantBuffer, FloatArray, ColorArray, VectorArray, MatrixArray)mode(ShaderPropertyMode, optional): Access mode - Default (Material), Global (Shader global), WithPropertyBlock (MaterialPropertyBlock extension), or Compute (ComputeShader)count(int, optional, default0): Declares a numbered group of properties instead of a single one.nameis used as the prefix and the index is appended to it, soname: "_Fill_"withcount: 5generates_Fill_1.._Fill_5, an array of their ids and indexed...Atmethods (see Numbered property groups).0means "not specified" — a single property is generated, exactly as without this parameterstartIndex(int, optional, default1): First index of a group declared withcount. UsestartIndex: 0for_Fill_0.._Fill_4
using UnityAttributes.ShaderProperty;
[ShaderProperty("_MainColor", ShaderPropertyType.Color)]
[ShaderProperty("_Metallic", ShaderPropertyType.Float)]
[ShaderProperty("_GlowIntensity", ShaderPropertyType.Float, ShaderPropertyMode.Global)]
public partial class MyShaderProperties
{
}
// Usage - Default mode (Material)
var material = GetComponent<Renderer>().material;
MyShaderProperties.SetMainColor(material, Color.red);
Color color = MyShaderProperties.GetMainColor(material);
// Usage - Global mode
MyShaderProperties.SetGlowIntensity(1.5f);
float intensity = MyShaderProperties.GetGlowIntensity();
// Usage - WithPropertyBlock mode
var propertyBlock = new MaterialPropertyBlock();
propertyBlock.SetMetallic(0.8f);
float metallic = propertyBlock.GetMetallic();Shaders often expose the same property repeated with an index suffix. Instead of one attribute per index, declare the group with count :
[ShaderProperty("_Fill_", ShaderPropertyType.Float, count: 5)]
[ShaderProperty("_SlotTexture_", ShaderPropertyType.Texture, count: 5)]
public partial class SlotProperties
{
}
// Every index still has its own members
SlotProperties.SetFill3(material, 0.5f);
// ...plus an ids array and ...At methods addressing it, so the group can be used in a loop
for (var i = 0; i < SlotProperties.Fill.Length; i++)
{
SlotProperties.SetFillAt(material, i, fillValues[i]);
}Every method generated for the type and mode gets an ...At counterpart taking an int index right after the target (material / propertyBlock / computeShader), and the At postfix goes at the very end of the name — SetSlotTextureOffsetAt(material, index, offset) . In Global mode there is no target, so the index comes first: SetGlowAt(index, color) .
Generated code
public partial class SlotProperties
{
public static readonly int Fill1 = Shader.PropertyToID("_Fill_1");
public static void SetFill1(Material material, float value)
{
material.SetFloat(Fill1, value);
}
public static float GetFill1(Material material)
{
return material.GetFloat(Fill1);
}
// ... Fill2 .. Fill5 ...
public static readonly int[] Fill =
{
Fill1,
Fill2,
Fill3,
Fill4,
Fill5,
};
public static void SetFillAt(Material material, int index, float value)
{
material.SetFloat(Fill[index], value);
}
public static float GetFillAt(Material material, int index)
{
return material.GetFloat(Fill[index]);
}
// ... the same for SlotTexture1 .. SlotTexture5, SlotTexture and SetSlotTextureAt ...
}Generated code
public partial class MyShaderProperties
{
public static readonly int MainColor = Shader.PropertyToID("_MainColor");
public static void SetMainColor(Material material, Color value)
{
material.SetColor(MainColor, value);
}
public static Color GetMainColor(Material material)
{
return material.GetColor(MainColor);
}
public static readonly int Metallic = Shader.PropertyToID("_Metallic");
public static void SetMetallic(Material material, float value)
{
material.SetFloat(Metallic, value);
}
public static float GetMetallic(Material material)
{
return material.GetFloat(Metallic);
}
public static readonly int GlowIntensity = Shader.PropertyToID("_GlowIntensity");
public static void SetGlowIntensity(float value)
{
Shader.SetGlobalFloat(GlowIntensity, value);
}
public static float GetGlowIntensity()
{
return Shader.GetGlobalFloat(GlowIntensity);
}
}Implements the Unity MonoBehaviour singleton pattern. The static Instance is set in the specified initialization method (e.g., Awake ).
Apply [Singleton("Awake")] to your partial MonoBehaviour class. The generator will create a static Instance property and set it in the specified method.
[Singleton("Awake")]
public partial class GameManager : MonoBehaviour
{
}
// Usage
GameManager.Instance.DoSomething();Generated code
public partial class GameManager : MonoBehaviour
{
public static GameManager Instance;
private void Awake()
{
Instance = this;
}
}