unity-scripting について
Unity 開発者向けの C# スクリプティングリファレンスです。ゲーム実行時とエディター用スクリプトを対象に、ライフサイクル、非同期処理、シリアライズ、API と注意点をまとめています。
主な機能
- 01MonoBehaviour のライフサイクルとコールバック
- 02コルーチンと Unity 6 Awaitable
- 03イベントと ScriptableObject のパターン
- 04シリアライズ規則と属性
- 05主要 API とよくあるアンチパターン
活用シーン
- 01ゲームロジックに使うコールバックの選択
- 02フレームをまたぐ非同期処理の実装
- 03設定やイベントデータの共有
- 04性能やライフサイクル上の問題の回避
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ nice-wolf-studio/ unity-claude-skills --skill unity-scriptingインストール後、Claude Code で/unity-scriptingを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/coroutines-and-async.mdmonobehaviour-lifecycle.mdobject-pool.mdscriptableobjects.md詳細
Unity C# スクリプティング
スクリプトの基本
C# スクリプト(.cs ファイル)は Assets フォルダーに保存されます。スクリプトは、組み込み型を継承することで Unity の機能を利用できます。
- UnityEngine.Object -- カスタム型を Inspector フィールドに割り当てられるようにします
- MonoBehaviour -- GameObject にコンポーネントとしてアタッチし、シーン内の動作を制御します
- ScriptableObject -- GameObject にアタッチされない、独立したデータアセットです
スクリプトは次の 2 つのコンテキストで動作します。
- ランタイムスクリプト -- Player ビルドで実行されます(
UnityEngine名前空間を使用) - エディタースクリプト -- エディター内でのみ実行されます(
UnityEditor名前空間を使用し、Editorフォルダーに配置します)
MonoBehaviour のライフサイクル
MonoBehaviour は常に GameObject のコンポーネントとして存在します。ライフサイクルイベント関数は厳密な順序で実行されます。Script Execution Order の設定で指定しない限り、異なる GameObject 間で同じイベント関数が呼び出される順序を前提にすることはできません。
実行順序(ASCII 図)
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
主なライフサイクルコールバック
| コールバック | タイミング | 用途 |
|---|---|---|
Awake() | スクリプトインスタンスの読み込み時 | 一度だけ行う初期化、参照のキャッシュ |
OnEnable() | コンポーネントの有効化時 | イベントの購読 |
Start() | 最初の Update の前 | 他の Awake() 呼び出しに依存する初期化 |
FixedUpdate() | 固定タイムステップ(デフォルト 0.02 秒) | 物理計算、Rigidbody の力 |
Update() | 毎フレーム | 入力、物理演算以外のゲームロジック |
LateUpdate() | すべての Update 呼び出しの後 | カメラの追従、Update 後の調整 |
OnDisable() | コンポーネントの無効化時 | イベントの購読解除 |
OnDestroy() | 破棄の前 | 最終的なクリーンアップ |
物理コールバック
// 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 のプロパティ(Unity 6)
| プロパティ | 用途 |
|---|---|
destroyCancellationToken | MonoBehaviour の破棄時に通知されるトークン(非同期処理のキャンセル用) |
didAwake | Awake が呼び出されたかどうか |
didStart | Start が呼び出されたかどうか |
runInEditMode | エディター内でのスクリプト実行を許可します |
ライフサイクルの詳細については、references/monobehaviour-lifecycle.md を参照してください。
コルーチンと Async/Await
Unity では、複数フレームにわたる処理を行う方法として、2 つのパターンがサポートされています。
コルーチン(IEnumerator)
yield return で中断し、yield 命令に基づいて再開するメソッドです。
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 命令:
yield return null-- 次のフレーム(Update の後)に再開しますyield return new WaitForSeconds(t)-- t 秒後に再開しますyield return new WaitForFixedUpdate()-- FixedUpdate の後に再開しますyield return new WaitForEndOfFrame()-- レンダリング後に再開しますyield return new WaitUntil(() => condition)-- 条件が true になったときに再開しますyield return StartCoroutine(other)-- 入れ子のコルーチンが完了するまで待機します
重要: コルーチンはメインスレッドで実行されます。enabled = false にして MonoBehaviour を無効にしても、コルーチンは停止しません。GameObject を非アクティブにするか、MonoBehaviour を破棄すると、コルーチンは停止します。
Awaitable(Unity 6 の Async/Await)
Awaitable は Unity 独自の非同期型で、通常はイテレーターを使うコルーチンよりも効率的です。割り当てを抑えるため、プールされています。
async Awaitable SampleSchedulingJobsForNextFrame()
{
await Awaitable.EndOfFrameAsync();
var jobHandle = ScheduleSomethingWithJobSystem();
await Awaitable.NextFrameAsync();
jobHandle.Complete();
}
Awaitable のメソッド:
Awaitable.NextFrameAsync()-- 次のフレームで再開しますAwaitable.FixedUpdateAsync()-- 次の FixedUpdate で再開しますAwaitable.EndOfFrameAsync()-- フレームの最後に再開しますAwaitable.WaitForSecondsAsync(float)-- 指定した時間の経過後に再開しますAwaitable.MainThreadAsync()-- メインスレッドで継続するように強制しますAwaitable.BackgroundThreadAsync()-- バックグラウンドスレッドで継続するように強制します
重要な制約: Awaitable インスタンスはプールされるため、同じインスタンスに対して await を複数回実行しないでください。複数回の await は未定義の動作を引き起こします。
| 機能 | コルーチン | Awaitable |
|---|---|---|
| 戻り値 | なし | あり(Awaitable<T>) |
| スレッド切り替え | なし | あり |
| メモリ割り当て | yield ごとにオーバーヘッドあり | プール済みで最小限 |
| キャンセル | StopCoroutine を手動で実行 | CancellationToken をサポート |
| エラー処理 | try/catch なし | try/catch/finally を完全サポート |
非同期処理の完全なリファレンス:references/coroutines-and-async.md
イベントと通信パターン
C# イベントとデリゲート
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 で割り当て可能)
using UnityEngine.Events;
public class GameManager : MonoBehaviour
{
public UnityEvent OnGameStart;
public UnityEvent<int> OnScoreChanged;
public void StartGame()
{
OnGameStart?.Invoke();
}
}
ScriptableObject のイベントチャネル
[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
ScriptableObject は、UnityEngine.Object を継承したシリアル化可能な Unity の型です。GameObject にアタッチされず、独立したプロジェクトアセットとして存在します。共有データ、設定、イベントチャネルに使用します。
[CreateAssetMenu(fileName = "Data", menuName = "ScriptableObjects/SpawnManagerScriptableObject", order = 1)]
public class SpawnManagerScriptableObject : ScriptableObject
{
public string prefabName;
public int numberOfPrefabsToCreate;
public Vector3[] spawnPoints;
}
主な動作:
- Edit モードでは Inspector での変更が自動的に保存されます。スクリプトによる変更には
EditorUtility.SetDirty()が必要です - 実行時、プレイヤーは ScriptableObject のデータを読み取れますが、変更をディスクに永続化することはできません
- メモリ効率に優れています。データを複製する代わりに、複数のオブジェクトが同じアセットインスタンスを参照します
ScriptableObject の完全なリファレンス:references/scriptableobjects.md
シリアル化クイックリファレンス
Unity は、以下のすべての条件を満たすフィールドをシリアル化します。
publicである、または[SerializeField]属性が付いているstatic、const、readonlyではない- シリアル化可能な型である
シリアル化可能な型: プリミティブ型、列挙型(32 ビット以下)、Unity 組み込み型(Vector2、Vector3、Rect、Color、AnimationCurve など)、[Serializable] を付けたカスタムクラス/構造体、UnityEngine.Object の参照、上記の型を要素とする List<T> および配列。
主な属性:
[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
サポート対象外: 多次元配列、ジャグ配列、辞書、ネストされたコンテナー。サポート対象外の型をカスタムシリアル化するには、ISerializationCallbackReceiver を使用します。
コア API クイックリファレンス
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);
プロパティ: magnitude、sqrMagnitude(比較に使用すると平方根の計算を避けられます)、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
x、y、z、w を直接変更しないでください。 Euler()、AngleAxis()、または 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);
一般的なパターン
コンポーネント参照のキャッシュ
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);
}
}
シングルトンパターン
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);
}
}
キャンセル処理付きの非同期処理(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);
}
}
条件付き待機(WaitUntil の Awaitable による置き換え)
public static async Awaitable AwaitableUntil(Func<bool> condition, CancellationToken token)
{
while (!condition())
{
token.ThrowIfCancellationRequested();
await Awaitable.NextFrameAsync();
}
}
アンチパターン
| アンチパターン | 問題 | 修正方法 |
|---|---|---|
Update() 内での GetComponent<T>() | 毎フレーム、割り当てが発生し、検索が行われます | Awake() でキャッシュします |
Update() 内での GameObject.Find() | 毎フレーム、高コストな文字列検索が行われます | 参照をキャッシュするか、シリアライズされたフィールドを使用します |
処理頻度の高い箇所で new Vector3() を繰り返す | 毎フレーム、不要なコンストラクターのオーバーヘッドが発生します | Vector3.zero、Vector3.one、または再利用可能な値をキャッシュして使用します |
Quaternion.x/y/z/w を直接変更する | 無効な回転が生成されます | Euler()、AngleAxis()、LookRotation() を使用します |
Update() 内で物理演算のロジックを実行する | フレームレートが変動すると一貫性が失われます | Rigidbody の力には FixedUpdate() を使用します |
FixedUpdate() 内で Time.deltaTime を使用する | 動作します(Unity が暗黙的に fixedDeltaTime を返します)が、読み手には分かりにくいです | 明確にするため、Time.fixedDeltaTime を明示的に使用します |
OnDisable でイベントの登録解除を忘れる | メモリーリークや null 参照エラーが発生します | 必ず OnDisable() で登録を解除します |
同じ Awaitable を 2 回 await する | 動作は未定義です(インスタンスがプールされるため) | 1 回だけ await するか、.AsTask() でラップします |
空の Update()/FixedUpdate() メソッド | Unity は引き続き呼び出すため、オーバーヘッドが発生します | 空のイベント関数を削除します |
文字列ベースの Invoke("MethodName", t) | コンパイル時の安全性がなく、名前の変更で動作しなくなります | 代わりにコルーチンまたは Awaitable を使用します |
関連スキル
- unity-foundations -- GameObject、コンポーネント、Transform、シーン、Prefab
- unity-physics -- Rigidbody、Collider、レイキャスト、物理マテリアル
- unity-input -- Input System、InputActions、PlayerInput コンポーネント
追加リソース
- スクリプティング | 実行順序 | コルーチン | 非同期処理/Await
- ScriptableObjects | MonoBehaviour | Vector3
- オブジェクトプーリング(
ObjectPool<T>)については、references/object-pool.md を参照してください