Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
8dee6d3
refactor: support properties in Weaver and delete PropertySiteProcessor
James-Frowen May 30, 2026
9a0eec2
feat: restrict SyncVarAttribute usage to properties
James-Frowen May 30, 2026
322ee06
test: update generator templates
James-Frowen May 30, 2026
2e9cc90
test: convert Weaver compiler tests and runtime tests to properties
James-Frowen May 30, 2026
9962bfc
docs: update guides and code examples to property-based SyncVars
James-Frowen May 30, 2026
642c74a
refactor: update Samples to use property-based SyncVars
James-Frowen May 30, 2026
00f2f9c
refactor: support properties in serialization attributes
James-Frowen May 30, 2026
41128cc
running test generator
James-Frowen May 30, 2026
b172a96
fix: fixing compile errors
James-Frowen May 30, 2026
158d358
fix: attribute
James-Frowen May 30, 2026
f01276a
updating components
James-Frowen May 30, 2026
5f1a3da
fix: support properties in attribute checks, copy packer attributes, …
James-Frowen May 31, 2026
300b18e
fix: removing () from property name
James-Frowen May 31, 2026
ca4dbe0
docs: updating docs for syncvar as properties
James-Frowen May 31, 2026
93172d1
feat: adding Warning when class is used as syncvar, and adding Weaver…
James-Frowen May 31, 2026
8287932
fix: changing to WeaverSafeClassAttribute and applying warning to net…
James-Frowen May 31, 2026
dfe921a
feat: adding c# Analyzers
James-Frowen May 31, 2026
26f2c37
docs: analyzer rules
James-Frowen May 31, 2026
3a02978
feat: more c# Analyzers
James-Frowen May 31, 2026
f1be60f
refactor: move c# Analyzers folders
James-Frowen May 31, 2026
ed4b817
test: Analyzer tests
James-Frowen May 31, 2026
0367b4f
valid c#/mirage test code
James-Frowen Jun 1, 2026
b567505
fixed tests
James-Frowen Jun 1, 2026
0b25b21
moving docs code to snippets
James-Frowen Jun 1, 2026
08cab5d
fixing rule MIRAGE1401
James-Frowen Jun 1, 2026
e43b48d
fix snippet compile errors
James-Frowen Jun 1, 2026
28751c9
fixing snippet compile errors
James-Frowen Jun 1, 2026
4977854
fix compile error
James-Frowen Jun 1, 2026
0a9742b
fixing compile errors
James-Frowen Jun 2, 2026
d1ea6f6
roadmap
James-Frowen Jun 2, 2026
f5fd1a8
docs
James-Frowen Jun 2, 2026
5676461
tests and meta files for samples
James-Frowen Jun 2, 2026
bd9acca
feat(Weaver): getting line context when attributes are used on wrong …
James-Frowen Jun 2, 2026
0affa17
size checking rule
James-Frowen Jun 2, 2026
624db6a
fixing snippet compile errors
James-Frowen Jun 2, 2026
48c0b47
asmdef for analyzer rules,
James-Frowen Jun 2, 2026
1bf50f8
feat: adding WeaverIgnoreAttribute for assemblies so Weaver will skip…
James-Frowen Jun 2, 2026
48b2f4b
tmp
James-Frowen Jun 2, 2026
2883da2
remove RoslynAnalyzer label until analyzer works
James-Frowen Jun 11, 2026
db7bed5
fix merge issues with syncvar properties
James-Frowen Jun 11, 2026
b4592ff
check for server.enabled
James-Frowen Jun 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
8 changes: 8 additions & 0 deletions Assets/Mirage/Analyzers.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file added Assets/Mirage/Analyzers/Mirage.Analyzers.dll
Binary file not shown.
71 changes: 71 additions & 0 deletions Assets/Mirage/Analyzers/Mirage.Analyzers.dll.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Assets/Mirage/Components/ReadyCheck.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class ReadyCheck : NetworkBehaviour
public event Action<bool> OnReadyChanged;

[SyncVar(hook = nameof(OnReadyChanged), invokeHookOnServer = true, invokeHookOnOwner = true)]
private bool _isReady;
private bool _isReady { get; set; }

public bool IsReady => _isReady;

Expand Down
2 changes: 1 addition & 1 deletion Assets/Mirage/Components/SyncObjectActive.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ public class SyncObjectActive : NetworkBehaviour
{
// todo update this to work with "invoke on sender" when syncvar has that setting
[SyncVar(hook = nameof(ActiveChanged), invokeHookOnServer = true)]
private bool _active;
private bool _active { get; set; }

private void ActiveChanged(bool nowActive)
{
Expand Down
3 changes: 1 addition & 2 deletions Assets/Mirage/Components/Visibility/NetworkMatchChecker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@ public class NetworkMatchChecker : NetworkVisibility
private static readonly Dictionary<Guid, HashSet<NetworkIdentity>> matchPlayers = new Dictionary<Guid, HashSet<NetworkIdentity>>();
private Guid currentMatch = Guid.Empty;

[Header("Diagnostics")]
[SyncVar]
public string currentMatchDebug;
public string currentMatchDebug { get; set; }

/// <summary>
/// Set this to the same value on all networked objects that belong to a given match
Expand Down
23 changes: 21 additions & 2 deletions Assets/Mirage/Runtime/CustomAttributes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Mirage
/// SyncVars are used to synchronize a variable from the server to all clients automatically.
/// <para>Value must be changed on server, not directly by clients. Hook parameter allows you to define a client-side method to be invoked when the client gets an update from the server.</para>
/// </summary>
[AttributeUsage(AttributeTargets.Field)]
[AttributeUsage(AttributeTargets.Property)]
public class SyncVarAttribute : PropertyAttribute
{
///<summary>A function that should be called on the client when the value changes.</summary>
Expand Down Expand Up @@ -36,6 +36,25 @@ public class SyncVarAttribute : PropertyAttribute
public SyncHookType hookType = SyncHookType.Automatic;
}

/// <summary>
/// Prevents Weaver warnings when using class-type SyncVars, NetworkMessage fields, or RPC parameters/return values.
/// <para>A class-type is generally UNSAFE because:
/// <list type="bullet">
/// <item>It will allocate a new object upon deserialization.</item>
/// <item>Mirage cannot track internal changes to the class.</item>
/// <item>It will fail SyncVar equality checks if setting the same instance (preventing dirty bit setting).</item>
/// </list>
/// </para>
/// <para>Mark a type or member with this attribute to declare it SAFE because:
/// <list type="bullet">
/// <item>It utilizes custom serialization/deserialization that manages safety/allocations.</item>
/// <item>It is serialized by ID/reference (like NetworkBehaviour/NetworkIdentity/GameObject).</item>
/// </list>
/// </para>
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Method)]
public class WeaverSafeClassAttribute : Attribute { }

public enum SyncHookType
{
/// <summary>
Expand Down Expand Up @@ -298,7 +317,7 @@ public sealed class ShowSyncSettingsAttribute : Attribute { }
/// or any custom type that has read/write overloads accepting an integer limit.
/// <para>This will use the Write/Read with length functions and will work on any type that has writers/readers for those.</para>
/// </summary>
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field)]
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)]
public class MaxLengthAttribute : Attribute
{
public readonly int maxLength;
Expand Down
17 changes: 10 additions & 7 deletions Assets/Mirage/Runtime/Serialization/WeaverAttributes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace Mirage.Serialization
/// <summary>
/// Tells Weaver to ignore a field or Method
/// </summary>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Field)]
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Assembly)]
public sealed class WeaverIgnoreAttribute : Attribute { }

/// <summary>
Expand Down Expand Up @@ -43,7 +43,7 @@ public WeaverSerializeCollectionAttribute() { }
/// </para>
/// <para>Also See: <see href="https://miragenet.github.io/Mirage/docs/guides/bit-packing/bit-countl">Bit Packing Documentation</see></para>
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter)]
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
public class BitCountAttribute : Attribute
{
/// <param name="bitCount">Value should be between 1 and 64</param>
Expand All @@ -54,7 +54,7 @@ public BitCountAttribute(int bitCount) { }
/// Calculates bitcount from then given min/max values and then packs using <see cref="BitCountAttribute"/>
/// <para>Also See: <see href="https://miragenet.github.io/Mirage/docs/guides/bit-packing/bit-count-from-range">Bit Packing Documentation</see></para>
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter)]
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
public class BitCountFromRangeAttribute : Attribute
{
/// <param name="min">minimum possible int value</param>
Expand All @@ -66,7 +66,7 @@ public BitCountFromRangeAttribute(int min, int max) { }
/// Used along size <see cref="BitCountAttribute"/> to encodes a integer value using <see cref="ZigZag"/> so that both positive and negative values can be sent
/// <para>Also See: <see href="https://miragenet.github.io/Mirage/docs/guides/bit-packing/bit-count-from-rangel">Bit Packing Documentation</see></para>
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter)]
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
public class ZigZagEncodeAttribute : Attribute
{
public ZigZagEncodeAttribute() { }
Expand All @@ -76,7 +76,7 @@ public ZigZagEncodeAttribute() { }
/// Packs a float field, clamped from -max to +max, with
/// <para>Also See: <see href="https://miragenet.github.io/Mirage/docs/guides/bit-packing/bit-count-from-range">Bit Packing Documentation</see></para>
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter)]
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
public class FloatPackAttribute : Attribute
{
/// <param name="max">Max value of the float</param>
Expand All @@ -91,6 +91,7 @@ public FloatPackAttribute(float max, int bitCount) { }
/// <summary>
///
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
public class Vector3PackAttribute : Attribute
{
public Vector3PackAttribute(float xMax, float yMax, float zMax, float xPrecision, float yPrecision, float zPrecision) { }
Expand All @@ -103,6 +104,7 @@ public Vector3PackAttribute(float xMax, float yMax, float zMax, int bitCount) {
/// <summary>
///
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
public class Vector2PackAttribute : Attribute
{
public Vector2PackAttribute(float xMax, float yMax, float xPrecision, float yPrecision) { }
Expand All @@ -115,6 +117,7 @@ public Vector2PackAttribute(float xMax, float yMax, int bitCount) { }
/// <summary>
///
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
public class QuaternionPackAttribute : Attribute
{
public QuaternionPackAttribute(int bitPerElement = 9) { }
Expand All @@ -125,7 +128,7 @@ public QuaternionPackAttribute(int bitPerElement = 9) { }
/// <para>Allows small values to be sent using less bits</para>
/// <para>Only works with integer fields (byte, int, ulong, enums etc)</para>
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter)]
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
public class VarIntAttribute : Attribute
{
public VarIntAttribute(ulong smallMax, ulong mediumMax) { }
Expand All @@ -139,7 +142,7 @@ public VarIntAttribute(ulong smallMax, ulong mediumMax, ulong largeMax, bool thr
/// <para>Allows small values to be sent using less bits</para>
/// <para>Only works with integer fields (byte, int, ulong, enums etc)</para>
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter)]
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
public class VarIntBlocksAttribute : Attribute
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public void OnStartServer()

// Color32 packs to 4 bytes
[SyncVar(hook = nameof(SetColor))]
public Color32 color = Color.black;
public Color32 color { get; set; } = Color.black;

// Unity clones the material when GetComponent<Renderer>().material is called
// Cache it here and destroy it in OnDestroy to prevent a memory leak
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Mirage.Examples.Additive
public class ShootingTankBehaviour : NetworkBehaviour
{
[SyncVar]
public Quaternion rotation;
public Quaternion rotation { get; set; }

public Animator animator;

Expand Down
6 changes: 3 additions & 3 deletions Assets/Mirage/Samples~/Basic/Scripts/BasicPlayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ public class BasicPlayer : NetworkBehaviour
// These are set in OnStartServer and used in OnStartClient

[SyncVar(initialOnly = true)] // playerNo is set on spawn so we can use initialOnly so it is only synced once
public int playerNo;
public int playerNo { get; set; }

[SyncVar]
private Color playerColor;
private Color playerColor { get; set; }

// This is updated by UpdateData which is called from OnStartServer via InvokeRepeating
[SyncVar(hook = nameof(OnPlayerDataChanged))]
public int playerData;
public int playerData { get; set; }

private void Awake()
{
Expand Down
2 changes: 1 addition & 1 deletion Assets/Mirage/Samples~/Chat/Scripts/Player.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Mirage.Examples.Chat
public class Player : NetworkBehaviour
{
[SyncVar]
public string playerName;
public string playerName { get; set; }

public static event Action<Player, string> OnMessage;

Expand Down
3 changes: 1 addition & 2 deletions Assets/Mirage/Samples~/InterestManagement/Scripts/Tank.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@ public class Tank : NetworkBehaviour
[Header("Movement")]
public float rotationSpeed = 100;

[Header("Game Stats")]
[SyncVar]
public string playerName;
public string playerName { get; set; }

public TextMesh nameText;

Expand Down
2 changes: 1 addition & 1 deletion Assets/Mirage/Samples~/MatchScenes/MatchScenesPlayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Mirage.Examples.MatchScenes
public class MatchScenesPlayer : NetworkBehaviour
{
[SyncVar]
public Color color;
public Color color { get; set; }

private void Awake()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ namespace Mirage.Examples.MultipleAdditiveScenes
public class PlayerScore : NetworkBehaviour
{
[SyncVar]
public int playerNumber;
public int playerNumber { get; set; }

[SyncVar]
public int scoreIndex;
public int scoreIndex { get; set; }

[SyncVar]
public int matchIndex;
public int matchIndex { get; set; }

[SyncVar]
public uint score;
public uint score { get; set; }

public int clientMatchIndex = -1;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public void OnStartServer()

// Color32 packs to 4 bytes
[SyncVar(hook = nameof(SetColor))]
public Color32 color = Color.black;
public Color32 color { get; set; } = Color.black;

// Unity clones the material when GetComponent<Renderer>().material is called
// Cache it here and destroy it in OnDestroy to prevent a memory leak
Expand Down
8 changes: 8 additions & 0 deletions Assets/Mirage/Samples~/Snippets/Analyzers.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Assets/Mirage/Samples~/Snippets/Analyzers/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[assembly: Mirage.Serialization.WeaverIgnore]

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "Mirage.Examples.Snippets.Analyzers",
"rootNamespace": "",
"references": [
"GUID:30817c1a0e6d646d99c048fc403f5979",
"GUID:f51ebe6a0ceec4240a699833d6309b23",
"GUID:96f081f4a0d214ee39e3aa34e9d43109",
"GUID:c0b2064c294eb174c9f3f7da398eb677",
"GUID:db69876fcdb4de041b3adaeefa87b6a6",
"GUID:bc6737b19bee94a798a182a84b660226"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading