この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:10
ページ更新者:atom
更新日時:2026-06-11 07:12:00

タイトル: スクリプト
SEOタイトル: Unity C# スクリプト完全入門 — MonoBehaviour・ライフサイクル・Inspector 連携

この記事の要点
  • Unity のスクリプトは C# + MonoBehaviour が基本。1 ファイル = 1 クラス推奨
  • 主要ライフサイクル: Awake → OnEnable → Start → Update → FixedUpdate → LateUpdate → OnDestroy
  • [SerializeField] で private フィールドも Inspector に出せる (推奨形)
  • GetComponent<T>() で同オブジェクトの Component を取得 (Start で取りキャッシュ)
  • 物理判定は OnCollisionEnter / OnTriggerEnter、時間処理は Coroutine

スクリプトの基本構造

Unity の C# スクリプトは Project ウィンドウで右クリック → Create → C# Script で生成します。デフォルトで MonoBehaviour を継承したクラスが入っています。

using UnityEngine;

public class PlayerController : MonoBehaviour {
    // Inspector に公開 (推奨)
    [SerializeField] private float speed = 5f;
    [SerializeField] private GameObject bulletPrefab;

    // 内部のみ
    private Rigidbody rb;

    void Awake() {
        // 自身の Component 取得は Awake / Start で
        rb = GetComponent<Rigidbody>();
    }

    void Start() {
        Debug.Log("ゲーム開始");
    }

    void Update() {
        // 入力など毎フレーム
        float h = Input.GetAxis("Horizontal");
        transform.Translate(Vector3.right * h * speed * Time.deltaTime);
    }
}

MonoBehaviour のライフサイクル

メソッドタイミング用途
Awake()インスタンス生成直後 (1 回)自分の Component 取得、初期化
OnEnable()有効化されるたびイベント購読
Start()最初の Update 直前 (1 回)他オブジェクト参照取得
Update()毎フレーム入力 / 移動 / 通常ロジック
FixedUpdate()固定間隔 (デフォ 0.02 秒)物理演算 / Rigidbody 操作
LateUpdate()全 Update 完了後カメラ追従
OnDisable()無効化時イベント解除
OnDestroy()破棄時リソース解放

[SerializeField] による Inspector 公開

public class Demo : MonoBehaviour {
    // public は外部から書き換え可能 (推奨されない)
    public int oldStyle;

    // private + [SerializeField] が現代の推奨
    [SerializeField] private int hp = 100;
    [SerializeField] private string playerName = &quot;勇者&quot;;
    [SerializeField] private Transform target;       // 参照型も OK
    [SerializeField] private GameObject[] enemies;   // 配列も OK

    // 範囲指定 (スライダー表示)
    [Range(0f, 100f)]
    [SerializeField] private float volume = 50f;

    // ヘッダで区切る
    [Header(&quot;移動設定&quot;)]
    [SerializeField] private float moveSpeed;
}

GetComponent でアクセス

// 同じ GameObject の Component
Rigidbody rb = GetComponent<Rigidbody>();
Animator anim = GetComponent<Animator>();

// 親 / 子から取得
Animator parentAnim = GetComponentInParent<Animator>();
Renderer[] childRends = GetComponentsInChildren<Renderer>();

// 他オブジェクトの Component
Transform target = GameObject.Find("Enemy").GetComponent<Transform>();

// null チェックの定石
if (TryGetComponent<Rigidbody>(out var rb2)) {
    rb2.AddForce(Vector3.up);
}

衝突判定 (Collision / Trigger)

// Collider.isTrigger = false の場合
void OnCollisionEnter(Collision col) {
    if (col.gameObject.CompareTag(&quot;Enemy&quot;)) {
        Debug.Log(&quot;敵と衝突: &quot; + col.contacts[0].point);
    }
}
void OnCollisionStay(Collision col) { /* 接触中 */ }
void OnCollisionExit(Collision col) { /* 離れた */ }

// isTrigger = true (すり抜け検知)
void OnTriggerEnter(Collider other) {
    if (other.CompareTag(&quot;Coin&quot;)) {
        Destroy(other.gameObject);
    }
}

コルーチン (時間処理)

using System.Collections;

public class CoroutineDemo : MonoBehaviour {
    void Start() {
        StartCoroutine(Sequence());
    }

    IEnumerator Sequence() {
        Debug.Log("1 秒待つ");
        yield return new WaitForSeconds(1f);

        Debug.Log("次のフレーム");
        yield return null;

        Debug.Log("FixedUpdate のタイミング");
        yield return new WaitForFixedUpdate();

        Debug.Log("条件待ち");
        yield return new WaitUntil(() => Input.GetKey(KeyCode.Space));

        Debug.Log("完了");
    }
}

Debug.Log で挙動確認

Debug.Log("普通のログ");
Debug.LogWarning("警告");
Debug.LogError("エラー");

// 値の出力
Debug.Log($"HP = {hp}, position = {transform.position}");

// 条件付き
Debug.Assert(hp > 0, "HP がマイナス");

// シーンビューに線を引く
Debug.DrawRay(transform.position, Vector3.forward * 5f, Color.red, 1f);

ScriptableObject (データ専用クラス)

シーンに属さない 共有データ を保存するアセット型です。武器の能力値や敵パラメータをテーブルで管理するのに最適。

using UnityEngine;

[CreateAssetMenu(fileName = &quot;WeaponData&quot;, menuName = &quot;Game/Weapon&quot;)]
public class WeaponData : ScriptableObject {
    public string weaponName;
    public int attack;
    public float range;
    public Sprite icon;
}

// 使う側
public class Player : MonoBehaviour {
    [SerializeField] private WeaponData currentWeapon;

    void Attack() {
        Debug.Log(currentWeapon.weaponName + &quot; で &quot; + currentWeapon.attack + &quot; ダメージ&quot;);
    }
}

推奨 IDE と設定

IDE無料特徴
Visual Studio○ (Community)Unity 公式推奨。デバッガ強い
JetBrains Rider個人非商用は無料Unity 専用解析が最強
VS Code + C# Dev Kit軽量。OmniSharp 設定が必要

パフォーマンス Tips

  • Update での GetComponent / Find を禁止。Awake / Start でキャッシュ
  • 毎フレーム文字列連結しない (GC アロケーション)
  • Vector3.Distance より sqrMagnitude 比較が速い
  • 大量オブジェクトは Object Pool パターン
  • 計算量の多い処理は Coroutine や Job System で分散

FAQ

Q: Update と FixedUpdate の使い分けは?
A: 入力や見た目は Update、Rigidbody 操作 (AddForce / velocity) は FixedUpdate。

Q: public と [SerializeField] private はどちらが良い?
A: 後者。public はカプセル化を壊し、他クラスから書き換えられるリスクがあります。

Q: スクリプトをアタッチしたら CompilerError が出る
A: クラス名とファイル名が完全一致しているか確認。PlayerController.csclass PlayerController