assembly-definitions
Assembly definition management — when to create asmdefs, reference rules, Editor/Runtime/Test separation, platform filters, compilation speed optimization.
Unity serialization rules — FormerlySerializedAs on renames, SerializeField vs public, SerializeReference for polymorphism, Unity null check (== null not ?.). CRITICAL: prevents silent data loss.
$ npx -y skills add XeldarAlz/everything-claude-unity --skill serialization-safety --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/serialization-safetyContext preview
The summary Claude sees to decide when to auto-load this skill.
Unity serialization rules — FormerlySerializedAs on renames, SerializeField vs public, SerializeReference for polymorphism, Unity null check (== null not ?.). CRITICAL: prevents silent data loss.
name: serialization-safety description: "Unity serialization rules — FormerlySerializedAs on renames, SerializeField vs public, SerializeReference for polymorphism, Unity null check (== null not ?.). CRITICAL: prevents silent data loss." alwaysApply: true
This is the single most important skill. Serialization mistakes cause **silent data loss** — every configured value in every scene, prefab, and ScriptableObject resets to default with zero warning.
// BEFORE: field is called _speed
[SerializeField] private float _speed = 5f;
// AFTER: renaming to _moveSpeed — MUST add FormerlySerializedAs
[FormerlySerializedAs("_speed")]
[SerializeField] private float _moveSpeed = 5f;**Why:** Unity serializes fields by name. Renaming breaks the name → value mapping. Every scene, prefab, and SO that configured this field silently loses its value. `[FormerlySerializedAs]` tells Unity "this field used to be called X."
The attribute stays **forever**. Never remove it.
// CORRECT — Unity overrides == to detect destroyed objects if (_target == null) return; if (_target != null) _target.TakeDamage(10); // WRONG — bypasses Unity's destroyed-object detection if (_target is null) return; // C# null check, misses destroyed _target?.TakeDamage(10); // ?. bypasses Unity ==, calls on destroyed _target ??= FindNewTarget(); // ??= uses C# null, not Unity null
**Why:** Unity objects can be "destroyed" (C++ side freed) but not yet garbage collected (C# reference still exists). Unity overrides `==` to return `true` for destroyed objects. C# pattern matching (`is null`, `?.`, `??`) uses reference equality, which returns `false` — so you call methods on destroyed objects, causing crashes or undefined behavior.
**Serialized:**
**NOT Serialized:**
// GOOD — controlled exposure [SerializeField] private float _health = 100f; public float Health => _health; // Read-only access // BAD — anyone can modify, clutters API public float health = 100f;
// Without SerializeReference: Unity serializes as base type, losing derived data [SerializeField] private IAbility _ability; // ERROR: interfaces not serialized // With SerializeReference: polymorphic serialization [SerializeReference] private IAbility _ability; // Works: stores concrete type
public class Enemy : MonoBehaviour
{
[SerializeField] private float _maxHealth = 100f;
[NonSerialized] public float CurrentHealth; // Runtime-only, not saved
private Transform _cachedTransform; // Private non-serialized by default (good)
}public class DataStore : MonoBehaviour, ISerializationCallbackReceiver
{
// Unity serializes these lists
[SerializeField] private List<string> _keys = new();
[SerializeField] private List<float> _values = new();
// Runtime dictionary (not serialized directly)
private Dictionary<string, float> _data = new();
public void OnBeforeSerialize()
{
_keys.Clear();
_values.Clear();
foreach (KeyValuePair<string, float> pair in _data)
{
_keys.Add(pair.Key);
_values.Add(pair.Value);
}
}
public void OnAfterDeserialize()
{
_data = new Dictionary<string, float>();
for (int i = 0; i < _keys.Count; i++)
{
_data[_keys[i]] = _values[i];
}
}
}Unity stops serializing at **7 levels** of nesting. Deeply nested data structures are silently truncated. If you need deep data, flatten it or use `[SerializeReference]`.
// C# 7.3+ syntax for serialized auto-properties
[field: SerializeField] public float Speed { get; private set; }
// Note: FormerlySerializedAs uses the backing field name:
[field: FormerlySerializedAs("<Speed>k__BackingField")]
[field: SerializeField] public float MoveSpeed { get; private set; }The ultimate Claude Code toolkit for Unity game development. A production-ready, plug-and-play system that gives Claude Code deep Unity expertise — from writing performant C# to building scenes, profiling performance, and triggering iOS/Android builds — all
Assembly definition management — when to create asmdefs, reference rules, Editor/Runtime/Test separation, platform filters, compilation speed optimization.
Structured commit trailers — adds Constraint, Rejected, Scope-risk, and Not-tested metadata to commit messages. Captures architectural decisions and known gaps…
Ambiguity gating — detects vague feature requests and forces structured requirements gathering with scoring across scope, platform, performance, integration,…
Event system patterns — C# events, UnityEvent, SO event channels, static EventBus. When to use each, zero-allocation patterns, memory leak prevention.
Configures Claude Code's statusline to display Unity workflow state — current phase, active agent, files modified, and session duration.
Post-debugging knowledge extraction — captures non-obvious, codebase-specific learnings that pass quality gates. Invoke after resolving tricky bugs or…