本文へ移動
cccskills
無料GitHub で公開

unity-scripting

Unity 6 C# scripting guide. Use when writing MonoBehaviour scripts, handling lifecycle events (Awake, Start, Update, FixedUpdate), using coroutines or async/await (Awaitable), working with ScriptableObjects, events, delegates, or core APIs like Vector3, Quaternion, Time, Debug. Based on Unity 6.3 LTS documentation.

インストール方法を見る

含まれるファイル(5)

  • SKILL.md16.2 KB
  • references/coroutines-and-async.md10.6 KB
  • references/monobehaviour-lifecycle.md10.3 KB
  • references/object-pool.md5.3 KB
  • references/scriptableobjects.md9.5 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Unity C# Scripting

Script Fundamentals

C# scripts (.cs files) are stored in the Assets folder. Scripts gain Unity functionality by inheriting from built-in types:

  • UnityEngine.Object -- Makes custom types assignable to Inspector fields
  • MonoBehaviour -- Attaches to GameObjects as components to control behavior in a scene
  • ScriptableObject -- Standalone data assets not attached to GameObjects

Scripts operate in two contexts:

  • Runtime scripts -- Execute in the Player build (use UnityEngine namespace)
  • Editor scripts -- Run only in the Editor (use UnityEditor namespace, place in Editor folders)

MonoBehaviour Lifecycle

MonoBehaviours always exist as a Component of a GameObject. The lifecycle event functions execute in a strict order. You cannot rely on the order in which the same event function is invoked for different GameObjects unless configured via Script Execution Order settings.

Execution Order (ASCII Diagram)

INITIALIZATION
  |
  v
[Awake] ---------> Called when script instance loads (once per lifetime)
  |
  v
[OnEnable] ------> Called when object/component becomes enabled
  |
  v
(SceneManager.sceneLoaded fires here -- after OnEnable, before Start)
  |
  v
[Start] ---------> Called before first frame Update (once per lifetime)
  |
  |
  |  +===========================================+
  |  |          PHYSICS LOOP (fixed timestep)    |
  |  |                                           |
  +->| [FixedUpdate] --> Internal Physics ------>|
  |  |       |                                   |
  |  | [yield WaitForFixedUpdate resumes]        |
  |  +===========================================+
  |
  v
[Update] --------> Called once per frame
  |
  v
[yield null / yield WaitForSeconds resumes]
  |
  v
(Internal Animation Update)
  |   [OnAnimatorMove]
  |   [OnAnimatorIK]
  |
  v
[LateUpdate] ----> Called after all Update functions complete
  |
  v
RENDERING
  | [OnWillRenderObject]
  | [OnPreCull] [OnBecameVisible/Invisible]
  | [OnPreRender]
  | [OnRenderObject]
  | [OnPostRender]
  | [OnRenderImage]
  |
  v
[OnGUI] ---------> Called for GUI rendering events
  |
  v
[yield WaitForEndOfFrame resumes]
  |
  v
DEACTIVATION / TEARDOWN
  |
  v
[OnDisable] -----> Called when component/object is disabled
  |
  v
[OnDestroy] -----> Called before object destruction

Key Lifecycle Callbacks

CallbackTimingUse For
Awake()Script instance loadsOne-time init, cache references
OnEnable()Component enabledSubscribe to events
Start()Before first UpdateInit that depends on other Awake() calls
FixedUpdate()Fixed timestep (default 0.02s)Physics calculations, Rigidbody forces
Update()Every frameInput, non-physics game logic
LateUpdate()After all Update callsCamera follow, post-Update adjustments
OnDisable()Component disabledUnsubscribe from events
OnDestroy()Before destructionFinal cleanup

Physics Callbacks

// 3D Physics
void OnCollisionEnter(Collision collision) { }
void OnCollisionStay(Collision collision) { }
void OnCollisionExit(Collision collision) { }
void OnTriggerEnter(Collider other) { }
void OnTriggerStay(Collider other) { }
void OnTriggerExit(Collider other) { }

// 2D Physics
void OnCollisionEnter2D(Collision2D collision) { }
void OnTriggerEnter2D(Collider2D other) { }

MonoBehaviour Properties (Unity 6)

PropertyPurpose
destroyCancellationTokenToken raised when MonoBehaviour is destroyed (for async cancellation)
didAwakeWhether Awake has been called
didStartWhether Start has been called
runInEditModeAllow script execution in editor

Full lifecycle reference: references/monobehaviour-lifecycle.md

Coroutines vs Async/Await

Unity supports two patterns for operations spanning multiple frames.

Coroutines (IEnumerator)

Methods that suspend with yield return and resume based on the yield instruction.

IEnumerator Fade()
{
    Color c = renderer.material.color;
    for (float alpha = 1f; alpha >= 0; alpha -= 0.1f)
    {
        c.a = alpha;
        renderer.material.color = c;
        yield return new WaitForSeconds(0.1f);
    }
}

void Update()
{
    if (Input.GetKeyDown("f"))
    {
        StartCoroutine(Fade());
    }
}

Yield Instructions:

  • yield return null -- Resume next frame (after Update)
  • yield return new WaitForSeconds(t) -- Resume after t seconds
  • yield return new WaitForFixedUpdate() -- Resume after FixedUpdate
  • yield return new WaitForEndOfFrame() -- Resume after rendering
  • yield return new WaitUntil(() => condition) -- Resume when condition is true
  • yield return StartCoroutine(other) -- Wait for nested coroutine

Important: Coroutines run on the main thread. Disabling the MonoBehaviour via enabled = false does NOT stop coroutines. Deactivating the GameObject or destroying the MonoBehaviour does stop them.

Awaitable (Unity 6 Async/Await)

Awaitable is Unity's custom async type -- usually more efficient than iterator-based coroutines. It is pooled to limit allocations.

async Awaitable SampleSchedulingJobsForNextFrame()
{
    await Awaitable.EndOfFrameAsync();
    var jobHandle = ScheduleSomethingWithJobSystem();
    await Awaitable.NextFrameAsync();
    jobHandle.Complete();
}

Awaitable Methods:

  • Awaitable.NextFrameAsync() -- Resume next frame
  • Awaitable.FixedUpdateAsync() -- Resume at next FixedUpdate
  • Awaitable.EndOfFrameAsync() -- Resume at end of frame
  • Awaitable.WaitForSecondsAsync(float) -- Resume after delay
  • Awaitable.MainThreadAsync() -- Force continuation on main thread
  • Awaitable.BackgroundThreadAsync() -- Force continuation on background thread

Critical constraint: Awaitable instances are pooled -- never await the same instance more than once. Multiple awaits cause undefined behavior.

FeatureCoroutineAwaitable
Return valuesNoYes (Awaitable<T>)
Thread switchingNoYes
Memory allocationPer-yield overheadPooled, minimal
CancellationManual StopCoroutineCancellationToken support
Error handlingNo try/catchFull try/catch/finally

Full async reference: references/coroutines-and-async.md

Events and Communication Patterns

C# Events and Delegates

public class Health : MonoBehaviour
{
    public event System.Action<float> OnDamageTaken;
    public event System.Action OnDeath;

    private float _hp = 100f;

    public void TakeDamage(float amount)
    {
        _hp -= amount;
        OnDamageTaken?.Invoke(amount);
        if (_hp <= 0f)
            OnDeath?.Invoke();
    }
}

public class UIHealthBar : MonoBehaviour
{
    [SerializeField] private Health _health;

    void OnEnable()
    {
        _health.OnDamageTaken += HandleDamage;
    }

    void OnDisable()
    {
        _health.OnDamageTaken -= HandleDamage;
    }

    private void HandleDamage(float amount)
    {
        // Update UI
    }
}

UnityEvents (Inspector-assignable)

using UnityEngine.Events;

public class GameManager : MonoBehaviour
{
    public UnityEvent OnGameStart;
    public UnityEvent<int> OnScoreChanged;

    public void StartGame()
    {
        OnGameStart?.Invoke();
    }
}

ScriptableObject Event Channels

[CreateAssetMenu(menuName = "Events/Void Event Channel")]
public class VoidEventChannel : ScriptableObject
{
    private System.Action _onEventRaised;

    public void RaiseEvent()
    {
        _onEventRaised?.Invoke();
    }

    public void Subscribe(System.Action listener) => _onEventRaised += listener;
    public void Unsubscribe(System.Action listener) => _onEventRaised -= listener;
}

ScriptableObjects

ScriptableObjects are serializable Unity types derived from UnityEngine.Object. They exist as independent project assets, not attached to GameObjects. Use them for shared data, configuration, and event channels.

[CreateAssetMenu(fileName = "Data", menuName = "ScriptableObjects/SpawnManagerScriptableObject", order = 1)]
public class SpawnManagerScriptableObject : ScriptableObject
{
    public string prefabName;
    public int numberOfPrefabsToCreate;
    public Vector3[] spawnPoints;
}

Key behaviors:

  • In Edit mode, Inspector modifications save automatically; script changes require EditorUtility.SetDirty()
  • At runtime, players can read ScriptableObject data but not persist modifications to disk
  • Memory efficient: multiple objects reference the same asset instance instead of duplicating data

Full ScriptableObject reference: references/scriptableobjects.md

Serialization Quick Reference

Unity serializes fields that meet ALL conditions:

  1. public OR has [SerializeField] attribute
  2. Not static, const, or readonly
  3. Is a serializable type

Serializable types: primitives, enums (32-bit or smaller), Unity built-in types (Vector2, Vector3, Rect, Color, AnimationCurve, etc.), [Serializable] custom classes/structs, UnityEngine.Object references, List<T> and arrays of any above type.

Key attributes:

[SerializeField] private float _speed = 5f;        // Serialize private field
[field: SerializeField] public float Speed { get; private set; } // Auto-property
[NonSerialized] public float tempValue;             // Exclude from serialization
[HideInInspector] public float hiddenValue;         // Serialize but hide from Inspector
[SerializeReference] private IMyInterface _impl;    // Polymorphic serialization

Not supported: Multidimensional arrays, jagged arrays, dictionaries, nested containers. Use ISerializationCallbackReceiver for custom serialization of unsupported types.

Core API Quick Reference

Vector3

// Static direction shortcuts
Vector3.zero;      // (0, 0, 0)
Vector3.one;       // (1, 1, 1)
Vector3.up;        // (0, 1, 0)
Vector3.forward;   // (0, 0, 1)
Vector3.right;     // (1, 0, 0)

// Common operations
float dist = Vector3.Distance(a, b);
float dot = Vector3.Dot(a.normalized, b.normalized);
Vector3 cross = Vector3.Cross(a, b);
Vector3 smoothed = Vector3.Lerp(from, to, t);
Vector3 moved = Vector3.MoveTowards(current, target, maxDelta);
Vector3 projected = Vector3.ProjectOnPlane(velocity, groundNormal);

Properties: magnitude, sqrMagnitude (use for comparisons -- avoids sqrt), normalized.

Quaternion

// Creation
Quaternion.identity;                             // No rotation
Quaternion.Euler(0f, 90f, 0f);                  // From Euler angles (degrees)
Quaternion.LookRotation(direction, Vector3.up);  // Face a direction
Quaternion.AngleAxis(45f, Vector3.up);           // Rotate around axis
Quaternion.FromToRotation(Vector3.up, normal);   // Rotation between directions

// Interpolation
Quaternion.Slerp(from, to, t);                  // Spherical interpolation
Quaternion.Lerp(from, to, t);                   // Linear interpolation

// Operations
float angle = Quaternion.Angle(a, b);           // Angle in degrees (0-180)
Vector3 rotatedPoint = rotation * point;         // Rotate a vector
Quaternion combined = rotA * rotB;               // Combine rotations

Never modify x, y, z, w directly. Use Euler(), AngleAxis(), or LookRotation().

Time

Time.deltaTime       // Seconds since last frame (use in Update)
Time.fixedDeltaTime  // Fixed timestep interval (use in FixedUpdate)
Time.time            // Time since game start
Time.timeScale       // 0 = paused, 1 = normal, 2 = double speed
Time.unscaledDeltaTime // Ignores timeScale (for UI animations during pause)

Debug

Debug.Log("Message");
Debug.LogWarning("Warning");
Debug.LogError("Error");
Debug.DrawRay(origin, direction, Color.red, duration);
Debug.DrawLine(start, end, Color.green, duration);

Common Patterns

Cached Component References

public class PlayerMovement : MonoBehaviour
{
    private Rigidbody _rb;
    private Transform _transform;

    void Awake()
    {
        _rb = GetComponent<Rigidbody>();
        _transform = transform; // Cache the transform property
    }

    void FixedUpdate()
    {
        // Use cached references -- never call GetComponent in Update/FixedUpdate
        _rb.AddForce(Vector3.up * 10f);
    }
}

Singleton Pattern

public class GameManager : MonoBehaviour
{
    public static GameManager Instance { get; private set; }

    void Awake()
    {
        if (Instance != null && Instance != this)
        {
            Destroy(gameObject);
            return;
        }
        Instance = this;
        DontDestroyOnLoad(gameObject);
    }
}

Async with Cancellation (Unity 6)

public class AsyncExample : MonoBehaviour
{
    async void Start()
    {
        try
        {
            await LoadAndProcessAsync(destroyCancellationToken);
        }
        catch (OperationCanceledException) { }
    }

    async Awaitable LoadAndProcessAsync(CancellationToken token)
    {
        await Awaitable.BackgroundThreadAsync();
        // Heavy computation here (off main thread)
        var result = ComputeExpensiveData();

        await Awaitable.MainThreadAsync();
        // Back on main thread -- safe to use Unity API
        ApplyResult(result);
    }
}

Conditional Wait (Awaitable replacement for WaitUntil)

public static async Awaitable AwaitableUntil(Func<bool> condition, CancellationToken token)
{
    while (!condition())
    {
        token.ThrowIfCancellationRequested();
        await Awaitable.NextFrameAsync();
    }
}

Anti-Patterns

Anti-PatternProblemFix
GetComponent<T>() in Update()Allocates and searches every frameCache in Awake()
GameObject.Find() in Update()Expensive string search every frameCache reference or use serialized field
Repeated new Vector3() in hot pathsUnnecessary constructor overhead each frameUse Vector3.zero, Vector3.one, or cache reusable values
Modifying Quaternion.x/y/z/w directlyProduces invalid rotationsUse Euler(), AngleAxis(), LookRotation()
Physics logic in Update()Inconsistent at variable frameratesUse FixedUpdate() for Rigidbody forces
Time.deltaTime in FixedUpdate()Works (Unity returns fixedDeltaTime implicitly) but is unclear to readersUse Time.fixedDeltaTime explicitly for clarity
Forgetting to unsubscribe events in OnDisableMemory leaks, null reference errorsAlways unsubscribe in OnDisable()
await-ing same Awaitable twiceUndefined behavior (pooled instances)Await once, or wrap with .AsTask()
Empty Update() / FixedUpdate() methodsUnity still calls them (overhead)Remove empty event functions
String-based Invoke("MethodName", t)No compile-time safety, breaks on renameUse coroutines or Awaitable instead

Related Skills

  • unity-foundations -- GameObjects, Components, Transforms, Scenes, Prefabs
  • unity-physics -- Rigidbody, Colliders, Raycasting, Physics materials
  • unity-input -- Input System, InputActions, PlayerInput component

Additional Resources

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

adopt

無料

Brownfield onboarding — audits existing project artifacts for template format compliance (not just existence), classifies gaps by impact, and produces a numbered migration plan. Run this when joining an in-progress project or upgrading from an older template version. Distinct from /project-stage-detect (which checks what exists) — this checks whether what exists will actually work with the template's skills.

日本語の概要は準備中です。原文の説明を表示しています。

IdoCohen560/claude-unity-game-studio222026年7月8日 更新

Creates an Architecture Decision Record (ADR) documenting a significant technical decision, its context, alternatives considered, and consequences. Every major technical choice should have an ADR.

日本語の概要は準備中です。原文の説明を表示しています。

IdoCohen560/claude-unity-game-studio222026年7月8日 更新

Validates completeness and consistency of the project architecture against all GDDs. Builds a traceability matrix mapping every GDD technical requirement to ADRs, identifies coverage gaps, detects cross-ADR conflicts, verifies engine compatibility consistency across all decisions, and produces a PASS/CONCERNS/FAIL verdict. The architecture equivalent of /design-review.

日本語の概要は準備中です。原文の説明を表示しています。

IdoCohen560/claude-unity-game-studio222026年7月8日 更新

art-bible

無料

Guided, section-by-section Art Bible authoring. Creates the visual identity specification that gates all asset production. Run after /brainstorm is approved and before /map-systems or any GDD authoring begins.

日本語の概要は準備中です。原文の説明を表示しています。

IdoCohen560/claude-unity-game-studio222026年7月8日 更新

Audits game assets for compliance with naming conventions, file size budgets, format standards, and pipeline requirements. Identifies orphaned assets, missing references, and standard violations.

日本語の概要は準備中です。原文の説明を表示しています。

IdoCohen560/claude-unity-game-studio222026年7月8日 更新

Generate per-asset visual specifications and AI generation prompts from GDDs, level docs, or character profiles. Produces structured spec files and updates the master asset manifest. Run after art bible and GDD/level design are approved, before production begins.

日本語の概要は準備中です。原文の説明を表示しています。

IdoCohen560/claude-unity-game-studio222026年7月8日 更新

IdoCohen560 のスキルをすべて見る

このスキルの問題を報告する