unity-core

v2026.09.24

Unity core scripting fundamentals — MonoBehaviour lifecycle, GameObject / Component model, ScriptableObjects, prefabs, serialization, coroutines, events, and execution order. USE WHEN: writing or refactoring core Unity scripts, designing data flow, setting up ScriptableObjects, dealing with serialization issues, choosing between Update / FixedUpdate / LateUpdate, coroutine vs async patterns. DO NOT USE FOR: rendering / shaders (use `unity-rendering`); 2D-specific topics (use `unity-2d-*`); networking (use `unity-netcode`); ECS/DOTS (use `unity-dots`).

GitHub
安装命令
npx skhub add claude-dev-suite/unity-core
Markdown
SKILL.md

Unity Core

MonoBehaviour Lifecycle

Awake          → once, per script instance, even if disabled
OnEnable       → each time GameObject/component becomes active
Start          → once, just before first Update, only if active
FixedUpdate    → fixed timestep (default 0.02s); physics writes here
Update         → every frame
LateUpdate     → after all Update; camera follow, IK adjustments
OnDisable      → when component/GO becomes inactive
OnDestroy      → when component/GO is destroyed (or app quits)

Order across objects: Awake/OnEnable for ALL objects, then Start for ALL, then per-frame loops. Tweak per-script via Edit > Project Settings > Script Execution Order — sparingly.

ScriptableObject — data assets

[CreateAssetMenu(menuName = "Game/Weapon", fileName = "NewWeapon")]
public class WeaponData : ScriptableObject {
    public string displayName;
    [Min(0)] public int damage = 10;
    [Range(0f, 5f)] public float fireRate = 0.5f;
    public Sprite icon;
    public AudioClip fireSfx;
}

Use them for: tuning data, configurable enemy stats, level definitions, event channels. Avoid them as runtime mutable singletons across scenes — values persist in editor between play sessions.

Reference injection (no Find)

public class Enemy : MonoBehaviour {
    [SerializeField] private WeaponData weapon;     // assigned in inspector
    [SerializeField] private Transform target;       // explicit dependency

    private Rigidbody _rb;                           // cached own component
    private void Awake() => _rb = GetComponent<Rigidbody>();
}

Never: GameObject.Find, FindObjectOfType in Update. Acceptable: once in Awake/Start when injection isn't possible (rare).

Coroutines vs async

Use casePick
Wait one frame / WaitForSeconds / WaitForFixedUpdateCoroutine — IEnumerator + yield return
HTTP / file IO / long async opsasync UniTask (UniTask package) or async Task with WhenAll
Cancellation / structured concurrencyUniTask + CancellationToken
Cross-platform WebGLCoroutines (no real threads) or UniTask
private Coroutine _flashRoutine;
private IEnumerator FlashRoutine() {
    var renderer = GetComponent<Renderer>();
    var original = renderer.material.color;
    for (int i = 0; i < 3; i++) {
        renderer.material.color = Color.red;
        yield return new WaitForSeconds(0.1f);
        renderer.material.color = original;
        yield return new WaitForSeconds(0.1f);
    }
    _flashRoutine = null;
}

public void Flash() {
    if (_flashRoutine != null) StopCoroutine(_flashRoutine);
    _flashRoutine = StartCoroutine(FlashRoutine());
}

Events — UnityEvent vs C# event vs ScriptableObject channel

StyleWhen
C# event Action<T>Internal cross-script communication, no inspector wiring
UnityEvent<T>Inspector-bound callbacks; designer-friendly
ScriptableObject event channelDecoupling across scenes / between systems with no direct reference

Serialization rules

  • [SerializeField] private over public for inspector exposure.
  • Lists/arrays of references serialize fine; cyclic references via [SerializeReference] only when needed (heavier).
  • Dictionary<TK,TV> does NOT serialize — use parallel List<TK>+List<TV> or SerializableDictionary packages.
  • For polymorphic data (e.g. behaviour trees), use [SerializeReference] + interfaces.

Anti-patterns

Anti-patternFix
Logic on every UpdateThrottle with if (Time.frameCount % N == 0) or events
Camera.main in UpdateCache once in Awake (_mainCam = Camera.main;)
transform.position writes inside FixedUpdate without RigidbodyUse rb.MovePosition, never transform.position for physics objects
Singleton MonoBehaviour with Instance accessed before AwakeMove init to Awake; use RuntimeInitializeOnLoadMethod for boot logic
Public mutable fields[SerializeField] private + property

Production checklist

  • Asmdefs split runtime / editor / test
  • No Find* calls in hot paths
  • All physics writes in FixedUpdate
  • ScriptableObjects used for tuning data
  • String hashes cached for Animator parameters
  • Events disposed in OnDisable / OnDestroy
  • Coroutines stopped on disable to avoid orphan loops
发现
标签

此技能尚未发布标签。

版本
最新版本元数据

版本

v2026.09.24

发布时间

Sep 24, 2026

分类

未分类

许可证

MIT

源路径

skills/gamedev/unity-core

默认分支

main

最新提交

9496306

Tree SHA

fe4e2f1