ai-behavior-trees-util…
Engine-neutral behavior tree and utility AI code for NPCs in any language: Blackboard, reactive composites, decorators and…
Unity 6.3 LTS data and decoupling with ScriptableObjects: CreateAssetMenu config assets, shared runtime variables, event channels and .asset files made from code. Use for replacing singletons, data-driven items or cards, or values that persist after leaving Play mode. Not for
Claude Code
$ npx -y skills add gamedev-skills/awesome-gamedev-agent-skills --skill unity-scriptableobjects --agent claude-code
Codex
$ npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill unity-scriptableobjects -a codex -y
Cursor
$ npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill unity-scriptableobjects -a cursor -y
Gemini CLI
$ npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill unity-scriptableobjects -a gemini-cli -y
GitHub Copilot
$ npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill unity-scriptableobjects -a github-copilot -y
OpenCode
$ npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill unity-scriptableobjects -a opencode -y
Windsurf
$ npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill unity-scriptableobjects -a windsurf -y
name: unity-scriptableobjects description: > Unity 6.3 LTS data and decoupling with ScriptableObjects: CreateAssetMenu config assets, shared runtime variables, event channels and .asset files made from code. Use for replacing singletons, data-driven items or cards, or values that persist after leaving Play mode. Not for saving progress (`save-systems`) or Godot Resources (`godot-resources`).
Use `ScriptableObject` assets in Unity 6.3 LTS (6000.3) for shared data and for decoupling systems: configuration, event channels and registries that live as project assets instead of scene singletons. An SO asset is a YAML file you can read and check without the Editor.
systems, senders and listeners that should not reference each other, a live registry of active objects without scene scans.
**When not to use:** state that differs per GameObject belongs on a MonoBehaviour, since an SO asset is shared by everyone who references it; saving progress → `save-systems`; plain data that never needs to be an asset can be a `[System.Serializable]` class.
1. **Define the class** deriving from `ScriptableObject`, in a file with the same name, with `[CreateAssetMenu]` so designers can create instances. 2. **Create the assets.** Designers use the Assets > Create menu. From code, use an editor script (pattern 3) so Unity writes the `.asset` and its `.meta` with a valid GUID. Do not hand-write a new `.asset` file: the `m_Script` GUID must match the script's `.meta`. 3. **Reference, do not copy.** MonoBehaviours hold a `[SerializeField]` reference; every consumer sees the same data. 4. **Keep mutable runtime state out of serialized fields** (`[System.NonSerialized]`) and reset it when Play mode starts (pattern 2), because Play-mode edits to an asset persist in the Editor. 5. **Make sure builds include the asset.** Only assets referenced from a scene in the build, from another included asset, from a `Resources` folder or from Addressables ship in the player. 6. **Verify** with the checks below.
using UnityEngine;
[CreateAssetMenu(fileName = "WeaponData", menuName = "Game/Weapon Data")]
public class WeaponData : ScriptableObject
{
public string displayName = "Pistol";
public int damage = 10;
public float fireRate = 0.25f;
public GameObject projectilePrefab;
}using UnityEngine;
[CreateAssetMenu(menuName = "Game/Float Variable")]
public class FloatVariable : ScriptableObject
{
[SerializeField] private float initialValue;
[System.NonSerialized] public float runtimeValue; // never saved to the asset
private void OnEnable()
{
runtimeValue = initialValue;
#if UNITY_EDITOR
// With Reload Domain off, OnEnable does not run again on Play, so also reset there.
UnityEditor.EditorApplication.playModeStateChanged -= ResetOnPlay;
UnityEditor.EditorApplication.playModeStateChanged += ResetOnPlay;
#endif
}
#if UNITY_EDITOR
private void OnDisable() => UnityEditor.EditorApplication.playModeStateChanged -= ResetOnPlay;
private void ResetOnPlay(UnityEditor.PlayModeStateChange change)
{
if (change == UnityEditor.PlayModeStateChange.ExitingEditMode) runtimeValue = initialValue;
}
#endif
}Put this in an `Editor` folder. Run it from the menu, from the Unity CLI with `unity command script eval --code 'WeaponAssets.CreateDefaults();'`, or in batch mode with `-executeMethod WeaponAssets.CreateDefaults`.
using UnityEditor;
using UnityEngine;
public static class WeaponAssets
{
[MenuItem("Tools/Create Default Weapons")]
public static void CreateDefaults()
{
if (!AssetDatabase.IsValidFolder("Assets/Data"))
AssetDatabase.CreateFolder("Assets", "Data");
var pistol = ScriptableObject.CreateInstance<WeaponData>();
pistol.displayName = "Pistol";
pistol.damage = 10;
AssetDatabase.CreateAsset(pistol, "Assets/Data/Pistol.asset"); // writes .asset and .meta
AssetDatabase.SaveAssets();
}
}To change an existing asset from editor code, load it with `AssetDatabase.LoadAssetAtPath<WeaponData>(path)`, set the fields, call `EditorUtility.SetDirty(asset)` and then `AssetDatabase.SaveAssets()`; without `SetDirty` the change is lost on the next reload.
with `m_Script: {fileID: 11500000, guid: ..., type: 3}`, `m_Name`, and one line per serialized field (`damage: 10`). Grep the values, and run `unity-csharp-scripting`'s `check_unity_project.py` to confirm every `m_Script` GUID resolves to a script.
`unity command script eval --code 'return AssetDatabase.LoadAssetAtPath<WeaponData>("Assets/Data/Pistol.asset").damage;'`
assert its values, or exercise an event channel with `ScriptableObject.CreateInstance` (setup in `unity-csharp-scripting`).
values shown on the asset in the Inspector changed.
Editor (not across launches of a build). Keep mutable state in `[NonSerialized]` fields and reset it.
off, loaded SOs are not recreated on Play, so `OnEnable` does not run. Also reset on `EditorApplicati
<img src="docs/assets/awesome-gamedev-agent-skills-banner.png" width="820" alt="awesome-gamedev-agent-skills — game-dev skills for AI coding agents.
Engine-neutral behavior tree and utility AI code for NPCs in any language: Blackboard, reactive composites, decorators and…
Engine-neutral game audio technique: bus layout, volume sliders in decibels, loudness, ducking music under dialogue, adaptive…
Builds and tunes game cameras, engine-neutral with Godot and Cinemachine 3 mappings: 2D follow with deadzone and look-ahead,…
Plans, generates or sources, and validates consistent game art: style guides, sprites, pixel art, tilesets, icons and textures,…
Builds engine-neutral branching dialogue with Ink, Yarn Spinner or a small JSON graph runner: lines, choices, conditions,…
Designs engine-neutral enemy and NPC AI: picks FSM, behavior tree, utility or GOAP, and builds perception, steering and A*…
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
Ask which skill or flow fits your situation. A router over the skills in this repo.