Version: Unity 6.5 Alpha (6000.5)
Language : English
Serialization rules
Custom serialization

Unity Serialization Analyzer

The Unity Serialization Analyzer is a Roslyn diagnostic analyzer that helps you write correct serialization code by detecting common mistakes and misuse of Unity’s serialization system at compile time. It provides real-time feedback in your IDE to prevent serialization issues before they cause runtime problems.

For detailed information about Unity’s serialization rules, refer to Script Serialization Rules.

Analyzer Rules

The serialization analyzer implements the following diagnostic rules:

UAC1000: SerializeReference field type missing

Severity: Warning

Description: When a field is serialized by [SerializeReference], its type must have the [Serializable] attribute. If the type is missing [Serializable], Unity issues a warning and the field will not serialize as expected. To suppress this warning add [Serializable] or use [MakeSerializable].

Example - Violation:

// Missing [Serializable] on CustomData
public class CustomData
{
    public int value;
}

public class MyBehaviour : MonoBehaviour
{
    [SerializeReference] public CustomData data; // UAC1000: CustomData lacks [Serializable]
}

Example - Fixed:

[System.Serializable] // Added [Serializable]
public class CustomData
{
    public int value;
}

public class MyBehaviour : MonoBehaviour
{
    [SerializeReference] public CustomData data; // OK
}

Why This Matters: Unity expects types used with [SerializeReference] to be explicitly marked as serializable. Marking the type with [Serializable] (or [MakeSerializable] when you cannot modify the type) prevents accidental omission that would otherwise drop serialized data.


UAC1001: Public field skipped by serialization due to missing

Severity: Warning

Description: Public fields of custom classes are candidates for serialization, but Unity will skip them if the class lacks the [Serializable] attribute. Without this attribute, Unity will not serialize the field, and you’ll lose data when entering play mode or when the sceneA Scene contains the environments and menus of your game. Think of each unique Scene file as a unique level. In each Scene, you place your environments, obstacles, and decorations, essentially designing and building your game in pieces. More info
See in Glossary
is saved. To fix this, you have three options: make the field private (if serialization is not desired), add [System.NonSerialized] (to explicitly mark it as non-serialized), or add [Serializable] to the type (if serialization is desired).

Example - Violation:

// Missing [Serializable] on PlayerStats
public class PlayerStats
{
    public int health;
    public int mana;
}

public class Player : MonoBehaviour
{
    public PlayerStats stats; // UAC1001: PlayerStats lacks [Serializable]
}

Example - Fixed:

[System.Serializable] // Added [Serializable]
public class PlayerStats
{
    public int health;
    public int mana;
}

public class Player : MonoBehaviour
{
    public PlayerStats stats; // OK - will be serialized inline
}

Why This Matters: Without [Serializable], Unity will skip the field during serialization, causing data loss. This is particularly problematic because the field will compile successfully but lose its value during serialization/deserialization cycles. The analyzer helps you catch this issue at compile time and provides clear guidance on how to fix it based on your intent (make it private, mark as non-serialized, or make the type serializable).


UAC1002: Inheritance hierarchy incomplete serialization

Severity: Warning

Description: The [Serializable] attribute is not inherited by derived classes. When using inheritance with serializable types, every class in the hierarchy must be explicitly marked with [Serializable]. If any class in the hierarchy is missing the attribute, serialization will fail for that entire type.

Example - Violation:

// Missing [Serializable] on base class
public class BaseEntity
{
    public string name;
}

[System.Serializable] // Derived class has [Serializable]
public class Enemy : BaseEntity
{
    public int damage;
}

public class GameManager : MonoBehaviour
{
    public Enemy enemy; // UAC1002: Enemy's hierarchy incomplete (BaseEntity lacks [Serializable])
}

Example - Fixed:

[System.Serializable] // Added [Serializable] to base class
public class BaseEntity
{
    public string name;
}

[System.Serializable]
public class Enemy : BaseEntity
{
    public int damage;
}

public class GameManager : MonoBehaviour
{
    public Enemy enemy; // OK - entire hierarchy is serializable
}

Alternative - Use [MakeSerializable] for Inaccessible Base Classes:

If you don’t have access to modify the base class (for example, it comes from a precompiled assembly or third-party library), you can use the [MakeSerializable] assembly attribute:

// In your own code - mark the external base class as serializable at assembly level
[assembly: UnityEngine.Serialization.MakeSerializable(typeof(ThirdPartyLibrary.BaseEntity))]

namespace ThirdPartyLibrary
{
    // This class is from a precompiled assembly - you cannot modify it
    public class BaseEntity
    {
        public string name;
    }
}

namespace YourGame
{
    [System.Serializable]
    public class Enemy : ThirdPartyLibrary.BaseEntity
    {
        public int damage;
    }

    public class GameManager : MonoBehaviour
    {
        public Enemy enemy; // OK - BaseEntity marked serializable via [MakeSerializable]
    }
}

Why This Matters: Unity requires all classes in an inheritance hierarchy to be explicitly marked as serializable. Missing the attribute on any class in the chain will cause serialization to fail, even if the base class is properly marked. The [MakeSerializable] attribute allows you to mark types as serializable without modifying their source code, which is essential when working with third-party libraries or precompiled assemblies.


UAC1003: [SerializeReference] used on struct

Severity: Error

Description: [SerializeReference] can only be used on reference types (classes). By definition, value types like structs cannot be serialized by reference because they are always copied by value. Using [SerializeReference] on a struct will cause a runtime error.

Example - Violation:

[System.Serializable]
public struct Vector3D // This is a struct (value type)
{
    public float x, y, z;
}

public class MyBehaviour : MonoBehaviour
{
    [SerializeReference] public Vector3D position; // UAC1003: Error - cannot use [SerializeReference] on struct
}

Example - Fixed:

[System.Serializable]
public struct Vector3D
{
    public float x, y, z;
}

public class MyBehaviour : MonoBehaviour
{
    public Vector3D position; // OK - structs are always serialized inline
}

Alternative - Use a Class:

[System.Serializable]
public class Vector3D // Changed to class (reference type)
{
    public float x, y, z;
}

public class MyBehaviour : MonoBehaviour
{
    [SerializeReference] public Vector3D position; // OK - class can use [SerializeReference]
}

Why This Matters: This is a fundamental type system constraint. Structs are value types and are always copied by value. [SerializeReference] is designed for reference semantics (null support, polymorphism, shared references), which are incompatible with value types. Unity will generate a runtime error if you attempt this.


UAC1004: [SerializeReference] used on primitive or enum type

Severity: Warning

Description: [SerializeReference] should only be used on reference types (classes). Using it on primitive types (int, float, bool, etc.) or enums has no effect because these are value types that are always serialized inline. The attribute will be silently ignored.

Example - Violation:

public enum GameState
{
    Menu,
    Playing,
    Paused
}

public class GameController : MonoBehaviour
{
    [SerializeReference] public int score; // UAC1004: int is a primitive type
    [SerializeReference] public GameState state; // UAC1004: GameState is an enum
}

Example - Fixed:

public enum GameState
{
    Menu,
    Playing,
    Paused
}

public class GameController : MonoBehaviour
{
    public int score; // OK - primitives don't need [SerializeReference]
    public GameState state; // OK - enums don't need [SerializeReference]
}

Why This Matters: Using [SerializeReference] on primitives and enums indicates a misunderstanding of how the attribute works. While it won’t cause errors, it clutters your code and may confuse other developers. These types are always serialized by value regardless of any attributes.


UAC1005: Direct self-reference cycle in serialized class

Severity: Warning

Description: When a class contains a field of its own type without using [SerializeReference], it creates a direct self-reference cycle. Unity’s inline serialization cannot handle this and will silently ignore the field during serialization. This means the field will always be null after serialization, causing unexpected data loss.

Example - Violation:

[System.Serializable]
public class Node
{
    public string data;
    public Node next; // UAC1005: Direct self-reference - Unity will ignore this field
}

public class LinkedList : MonoBehaviour
{
    public Node head; // After serialization, head.next will always be null
}

Example - Fixed with [SerializeReference]:

[System.Serializable]
public class Node
{
    public string data;
    [SerializeReference] public Node next; // OK - [SerializeReference] supports cycles
}

public class LinkedList : MonoBehaviour
{
    [SerializeReference] public Node head; // OK - preserves linked structure
}

Alternative - Redesign to Avoid Cycle:

[System.Serializable]
public class NodeData
{
    public string data;
    public int nextIndex; // Store index instead of direct reference
}

public class LinkedList : MonoBehaviour
{
    public NodeData[] nodes; // OK - no direct cycles
}

Why This Matters: Inline serialization copies objects by value, which cannot represent cycles. Unity detects this at runtime and silently ignores such fields to prevent infinite loops during serialization. This causes data loss that can be difficult to debug.


UAC1006: Field uses type with direct self-reference cycle

Severity: Warning

Description: When you use a type that contains a direct self-reference cycle (as detected by UAC1005), Unity will ignore that field during serialization. This warning appears at the usage site to alert you that the field won’t be serialized properly.

Example - Violation:

[System.Serializable]
public class TreeNode
{
    public string value;
    public TreeNode left; // Direct self-reference
    public TreeNode right; // Direct self-reference
}

public class Tree : MonoBehaviour
{
    public TreeNode root; // UAC1006: TreeNode contains self-reference cycles
    // After serialization, the root field will be ignored and remain null
}

Example - Fixed:

[System.Serializable]
public class TreeNode
{
    public string value;
    [SerializeReference] public TreeNode left; // Fixed with [SerializeReference]
    [SerializeReference] public TreeNode right; // Fixed with [SerializeReference]
}

public class Tree : MonoBehaviour
{
    [SerializeReference] public TreeNode root; // OK - preserves tree structure
}

Why This Matters: This warning helps you catch data loss issues at compile time. It alerts you when you’re using a type that has serialization problems, even if you didn’t write that type yourself.


UAC1007: Deep self-reference cycle in serialized class

Severity: Warning

Description: When a class contains fields that create an indirect cycle (A → B → A or A → B → C → A), Unity will serialize the structure but limits recursion to 10 levels deep. After 10 levels, Unity stops serializing and cuts off the remaining data, causing potential data loss. This warning appears on the field that creates the cycle.

Example - Violation:

[System.Serializable]
public class Parent
{
    public string name;
    public Child child; // UAC1007: Creates deep cycle (Parent → Child → Parent)
}

[System.Serializable]
public class Child
{
    public string name;
    public Parent parent; // Creates the cycle back to Parent
}

public class Family : MonoBehaviour
{
    public Parent root; // Will serialize up to 10 levels: Parent→Child→Parent→Child...
}

Example - Fixed with [SerializeReference]:

[System.Serializable]
public class Parent
{
    public string name;
    [SerializeReference] public Child child; // OK - [SerializeReference] handles cycles
}

[System.Serializable]
public class Child
{
    public string name;
    [SerializeReference] public Parent parent; // OK - preserves bidirectional relationship
}

public class Family : MonoBehaviour
{
    [SerializeReference] public Parent root; // OK - no depth limit
}

Alternative - Redesign Structure:

[System.Serializable]
public class Parent
{
    public string name;
    public List<string> childNames; // Store references differently
}

[System.Serializable]
public class Child
{
    public string name;
    public string parentName; // Use name lookup instead of direct reference
}

public class Family : MonoBehaviour
{
    public List<Parent> parents; // OK - no cycles
    public List<Child> children; // OK - no cycles
}

Why This Matters: While Unity does serialize deep cycles (unlike direct cycles), the 10-level limit can cause silent data loss in deeply nested structures. This is particularly problematic for tree or graph structures where you might not realize your data is being truncated.


UAC1008: Field uses type with deep self-reference cycle

Severity: Warning

Description: When you use a type that contains a deep self-reference cycle (as detected by UAC1007), Unity will serialize it with a 10-level recursion limit. This warning appears at the usage site to alert you that deep instances of this type may experience data loss.

Example - Violation:

[System.Serializable]
public class GraphNode
{
    public string id;
    public List<GraphNode> connections; // Creates deep cycles
}

public class Graph : MonoBehaviour
{
    public List<GraphNode> nodes; // UAC1008: GraphNode contains deep cycles
    // Deep graph structures (>10 levels) will be truncated
}

Example - Fixed:

[System.Serializable]
public class GraphNode
{
    public string id;
    [SerializeReference] public List<GraphNode> connections; // OK - no depth limit
}

public class Graph : MonoBehaviour
{
    [SerializeReference] public List<GraphNode> nodes; // OK - handles arbitrary depth
}

Alternative - Use IDs:

[System.Serializable]
public class GraphNode
{
    public string id;
    public List<string> connectionIds; // Store IDs instead of references
}

public class Graph : MonoBehaviour
{
    public List<GraphNode> nodes; // OK - no cycles, resolve IDs at runtime
    
    public GraphNode FindNode(string id)
    {
        return nodes.Find(n => n.id == id);
    }
}

Why This Matters: This warning helps you identify when you’re using types that have depth-limited serialization. It’s especially important for complex data structures like graphs, where the 10-level limit might not be immediately obvious until data loss occurs in production.


UAC1009: Unsupported collection type for serialization

Severity: Warning

Description: Unity’s serialization system only supports specific collection types: single-dimensional arrays (T[]) and List<T>. Multidimensional arrays (e.g., int[,], int[,,]), jagged arrays (e.g., int[][]), and other generic collections from System.Collections.Generic such as Dictionary<TKey, TValue>, HashSet<T>, Queue<T>, and Stack<T> are not supported and will be silently ignored during serialization. This can lead to unexpected data loss when fields of these types are not persisted.

Example - Violation:

public class InventorySystem : MonoBehaviour
{
    public int[,] grid; // UAC1009: Multidimensional array not supported
    public int[][] jaggedArray; // UAC1009: Jagged array not supported
    public Dictionary<string, int> itemCounts; // UAC1009: Dictionary not supported
    public HashSet<string> unlockedAchievements; // UAC1009: HashSet not supported
    public Queue<string> messageQueue; // UAC1009: Queue not supported
    public Stack<string> undoStack; // UAC1009: Stack not supported
    
    // These fields will NOT be serialized and will lose their values
}

Example - Fixed with [NonSerialized]:

If you don’t need these fields to persist (for example, they are runtime-only data structures), mark them with [System.NonSerialized] to acknowledge they won’t be serialized and suppress the warning:

public class InventorySystem : MonoBehaviour
{
    [System.NonSerialized] public Dictionary<string, int> itemCounts; // OK - explicitly marked as non-serialized
    [System.NonSerialized] public HashSet<string> unlockedAchievements; // OK - runtime-only data
    [System.NonSerialized] public Queue<string> messageQueue; // OK - transient queue
    [System.NonSerialized] public Stack<string> undoStack; // OK - runtime undo stack
    
    private void Awake()
    {
        // Initialize runtime collections
        itemCounts = new Dictionary<string, int>();
        unlockedAchievements = new HashSet<string>();
        messageQueue = new Queue<string>();
        undoStack = new Stack<string>();
    }
}

Alternative - Use Supported Collections:

If you need the data to persist, convert to supported collection types:

[System.Serializable]
public struct KeyValuePair
{
    public string key;
    public int value;
}

public class InventorySystem : MonoBehaviour
{
    public List<KeyValuePair> itemCounts; // OK - List is supported
    public List<string> unlockedAchievements; // OK - List instead of HashSet
    public List<string> messageQueue; // OK - List instead of Queue
    public List<string> undoStack; // OK - List instead of Stack
    
    // Helper methods to maintain collection semantics
    public int GetItemCount(string itemName)
    {
        var pair = itemCounts.Find(p => p.key == itemName);
        return pair.value;
    }
    
    public void SetItemCount(string itemName, int count)
    {
        int index = itemCounts.FindIndex(p => p.key == itemName);
        if (index >= 0)
            itemCounts[index] = new KeyValuePair { key = itemName, value = count };
        else
            itemCounts.Add(new KeyValuePair { key = itemName, value = count });
    }
}

Alternative - Use SerializableHashSet (Custom Implementation):

[System.Serializable]
public class SerializableHashSet<T>
{
    [SerializeField] private List<T> items = new List<T>();
    
    private HashSet<T> hashSet;
    
    public void OnBeforeSerialize()
    {
        items.Clear();
        if (hashSet != null)
            items.AddRange(hashSet);
    }
    
    public void OnAfterDeserialize()
    {
        hashSet = new HashSet<T>(items);
    }
    
    public bool Add(T item) => hashSet.Add(item);
    public bool Contains(T item) => hashSet.Contains(item);
    public bool Remove(T item) => hashSet.Remove(item);
    public int Count => hashSet.Count;
}

public class AchievementManager : MonoBehaviour
{
    public SerializableHashSet<string> unlockedAchievements; // OK - custom serializable wrapper
}

Alternative - Dictionary with Separate Key/Value Lists:

[System.Serializable]
public class SerializableDictionary<TKey, TValue>
{
    [SerializeField] private List<TKey> keys = new List<TKey>();
    [SerializeField] private List<TValue> values = new List<TValue>();
    
    [System.NonSerialized] private Dictionary<TKey, TValue> dictionary;
    
    public void OnBeforeSerialize()
    {
        keys.Clear();
        values.Clear();
        
        if (dictionary != null)
        {
            foreach (var kvp in dictionary)
            {
                keys.Add(kvp.Key);
                values.Add(kvp.Value);
            }
        }
    }
    
    public void OnAfterDeserialize()
    {
        dictionary = new Dictionary<TKey, TValue>();
        
        for (int i = 0; i < keys.Count && i < values.Count; i++)
        {
            dictionary[keys[i]] = values[i];
        }
    }
    
    public TValue this[TKey key]
    {
        get => dictionary[key];
        set => dictionary[key] = value;
    }
    
    public bool TryGetValue(TKey key, out TValue value) => dictionary.TryGetValue(key, out value);
    public bool ContainsKey(TKey key) => dictionary.ContainsKey(key);
    public void Add(TKey key, TValue value) => dictionary.Add(key, value);
    public bool Remove(TKey key) => dictionary.Remove(key);
    public int Count => dictionary.Count;
}

public class ItemDatabase : MonoBehaviour
{
    public SerializableDictionary<string, int> itemPrices; // OK - serializes as separate key/value lists
}

Why This Matters: Unity’s serialization system has specific limitations on which collection types it supports. Using unsupported collections like Dictionary, HashSet, Queue, or Stack means your data will silently disappear during serialization. This can lead to difficult-to-debug issues where fields appear to work fine at runtime but lose their values when entering play mode, saving scenes, or building your project. By catching this at compile time, you can either mark the field as [NonSerialized] if it’s runtime-only data, or convert to a supported collection type to ensure your data persists correctly.

Note: UAC1009 also applies when unsupported collections appear as element types inside arrays or List<T> (for example, List<Dictionary<string, int>> or Dictionary<string, int>[]). These will also be flagged because their elements cannot be serialized by Unity.

Note: UAC1009 also flags nested lists (e.g., List<List<T>>, List<List<Dictionary<string, int>>>) because Unity does not support serializing lists of lists.

Note: Multidimensional arrays (e.g., int[,], int[,,]) and jagged arrays (e.g., int[][], int[][][]) are explicitly flagged by UAC1009 as Unity only supports single-dimensional arrays (T[]).


UAC1010: [SerializeField] used on non-serializable type

Severity: Warning

Description: When you use [SerializeField] on a field whose type is not [Serializable], Unity will silently ignore the field during serialization. The [SerializeField] attribute has no effect on non-serializable types, and the field will not be persisted. This warning suggests either replacing [SerializeField] with [System.NonSerialized] to explicitly mark the field as non-serialized, or making the type [Serializable] if serialization is actually desired.

Example - Violation:

// Missing [Serializable] on MyWindowState
public class MyWindowState : BaseState
{
    public List<int> expandedItems;
}

public class MyWindowManager : ScriptableObject
{
    [SerializeField] public MyWindowState windowState; // UAC1010: Unity will ignore this field
}

Example - Fixed with [NonSerialized]:

If the field doesn’t need to be serialized (for example, it’s runtime-only state), replace [SerializeField] with [System.NonSerialized]:

public class MyWindowState : BaseState
{
    public List<int> expandedItems;
}

public class MyWindowManager : ScriptableObject
{
    [System.NonSerialized] public MyWindowState windowState; // OK - explicitly marked as non-serialized
}

Example - Fixed with Serializable:

If you need the field to be serialized, make the type [Serializable]:

[System.Serializable] // Added [Serializable]
public class MyWindowState : BaseState
{
    public List<int> expandedItems;
}

public class MyWindowManager : ScriptableObject
{
    [SerializeField] public MyWindowState windowState; // OK - type is now serializable
}

Why This Matters: Using [SerializeField] on a non-serializable type is misleading because Unity will silently ignore the field. This can lead to confusion where developers expect the field to be serialized but it isn’t. By explicitly using [System.NonSerialized], you make it clear that the field is intentionally not serialized. Alternatively, if serialization is desired, marking the type as [Serializable] ensures the field will actually be persisted.


UAC1011: Enum type exceeds 32-bit size limit

Severity: Warning

Description: Unity’s serialization system only supports enum types that are 32 bits or smaller. Enums with underlying types of long (64-bit signed) or ulong (64-bit unsigned) exceed this limit and will not be serialized correctly. Unity will silently ignore fields of these types during serialization, causing data loss.

Example - Violation:

public enum LargeEnum : long
{
    Value1 = 1L,
    Value2 = 2L,
    Value3 = long.MaxValue
}

public class GameData : MonoBehaviour
{
    public LargeEnum {|#0:largeEnum|}; // UAC1011: 64-bit enum exceeds Unity's 32-bit limit
}

Example - Fixed with Smaller Underlying Type:

public enum SmallEnum : int  // int is 32-bit, which is within Unity's limit
{
    Value1 = 1,
    Value2 = 2,
    Value3 = int.MaxValue
}

public class GameData : MonoBehaviour
{
    public SmallEnum smallEnum; // OK - 32-bit enum is supported
}

Example - Fixed with [NonSerialized]:

If you don’t need the enum field to persist (for example, it’s runtime-only state), mark it with [System.NonSerialized]:

public enum LargeEnum : long
{
    Value1 = 1L,
    Value2 = 2L
}

public class GameData : MonoBehaviour
{
    [System.NonSerialized] public LargeEnum largeEnum; // OK - explicitly marked as non-serialized
    
    private void Awake()
    {
        // Initialize runtime enum value
        largeEnum = LargeEnum.Value1;
    }
}

Why This Matters: Unity’s serialization system has a 32-bit limit for enum types. Using 64-bit enums (long or ulong) means your field will silently disappear during serialization. This can lead to difficult-to-debug issues where enum fields appear to work fine at runtime but lose their values when entering play mode, saving scenes, or building your project. By catching this at compile time, you can either mark the field as [NonSerialized] if it’s runtime-only data, or change the enum’s underlying type to int or smaller to ensure your data persists correctly.

Note: Unity supports enum underlying types of byte, sbyte, short, ushort, int, and uint (all 32 bits or smaller). Only long and ulong (64-bit) are unsupported.


Known Limitations

Base Class Field Analysis

The analyzer only analyzes fields on serialization roots (types marked with [Serializable], types inheriting from UnityEngine.Object, etc.). Base classes that are not serialization roots do not have their fields analyzed, even if they are part of an inheritance hierarchy with serialization roots.

Example:

// Base class is NOT a serialization root
public class BaseClass
{
    public Dictionary<string, int> settings; // Will NOT trigger UAC1009
    public CustomData data; // Will NOT trigger UAC1001
}

public class CustomData { }

[System.Serializable] // Derived class IS a serialization root
public class DerivedClass : BaseClass
{
    public int value; // This field WILL be analyzed
}

What Happens:

  • UAC1002 is always reported on DerivedClass because its base class BaseClass lacks [Serializable] (inheritance hierarchy incomplete serialization)
  • No warnings are reported for BaseClass fields (settings and data) because BaseClass is not a serialization root

Solution - Make Base Class a Serialization Root:

If you need base class fields to be validated, mark the base class as a serialization root:

[System.Serializable] // Added [Serializable] - now BaseClass is a serialization root
public class BaseClass
{
    public Dictionary<string, int> settings; // UAC1009: Will be reported
    public CustomData data; // UAC1001: Will be reported
}

public class CustomData { }

[System.Serializable]
public class DerivedClass : BaseClass
{
    public int value;
}

Why This Design:

  • Analyzing only serialization roots provides consistent, predictable behavior
  • Eliminates race conditions that could occur with concurrent analysis
  • Improves performance by reducing the number of types analyzed
  • In practice, base classes that need serialization validation should be marked as [Serializable] anyway, making them serialization roots

Best Practices

  1. Always use [Serializable] on custom classes: Make it a habit to add [Serializable] to any class you intend to serialize, whether using inline serialization or [SerializeReference].

  2. Mark entire inheritance hierarchies: Remember that [Serializable] is not inherited. Every class in a hierarchy must be explicitly marked.

  3. Use [SerializeReference] for complex relationships: If your data structure involves null references, polymorphism, shared references, or cycles, use [SerializeReference] instead of inline serialization.

  4. Avoid cycles in inline serialization: If you’re not using [SerializeReference], design your data structures to avoid cycles. Use indices, IDs, or other indirect references instead.

  5. Be aware of the 10-level limit: Even with deep cycles that Unity attempts to serialize, there’s a 10-level recursion limit. Design your data structures accordingly or use [SerializeReference].

  6. Value types are always inline: Remember that structs, primitives, and enums are always serialized by value. [SerializeReference] only works with reference types (classes).

Suppressing Warnings

If you have a valid reason to suppress a specific analyzer warning, you can use #pragma warning disable:

#pragma warning disable UAC1001
public class IntentionallyUnserializedClass
{
    public int value;
}
#pragma warning restore UAC1001

However, suppressing these warnings is rarely needed, as they indicate actual serialization issues that will cause problems at runtime.

Additional Resources

Serialization rules
Custom serialization