界面已本地化;技能介绍与说明文档按所选语言由 AI 自动翻译,代码、命令、路径和专业术语保留原文,以原作者文档为准。
探索技能
设计与创意 · SKILL.md

unity-core

unity-core

【设计与创意】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…

独立 GitHub 快照 · 自动分类 · 以原作者文档为准

技能说明

GitHub

name: unity-core description: | 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). allowed-tools: Read, Grep, Glob, Write, Edit

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
我的收藏