Unityゲーム開発基礎

組み立ての単位

Unity では、シーン(1つの画面・ステージ)の上に GameObject を置き、GameObject に コンポーネントを貼り付けて振る舞いを与えます。

Scene
└─ GameObject "Player"
   ├─ Transform      … 位置・回転・大きさ(必ず付く)
   ├─ SpriteRenderer … 見た目
   ├─ Rigidbody2D    … 物理
   └─ PlayerControl  … 自分で書くスクリプト([[C#/.NET]])

GameObject 自体は空の入れ物です。 「プレイヤー」という型があるのではなく、必要な部品を組み合わせた結果がプレイヤーになります。継承ではなく組み合わせで振る舞いを作るのがこのモデルの中心です。

同じ構成を繰り返し使うときは Prefab として保存します。敵キャラを100体出すなら、Prefab を1つ作って複製します。Prefab を直すと配置済みのすべてに反映されます。

毎フレーム呼ばれる前提

自分で書くスクリプトは、決まった名前のメソッドがエンジンから呼ばれます。

メソッドいつ呼ばれるか
Awake / Start生成時に1回
Update毎フレーム(端末の性能で回数が変わる)
FixedUpdate一定間隔(物理演算用)
OnDestroy破棄時

Update と FixedUpdate の使い分けが最初の分岐点です。

void Update() {
    // 入力の検出はここ。取りこぼさない
    if (Input.GetKeyDown(KeyCode.Space)) _jumpRequested = true;
}

void FixedUpdate() {
    // 物理の適用はここ。フレームレートに依らず一定
    if (_jumpRequested) { _rb.AddForce(Vector2.up * 5f, ForceMode2D.Impulse); _jumpRequested = false; }
}

物理の操作を Update に書くと、60fpsの端末と144fpsの端末で挙動が変わります。逆に入力の検出を FixedUpdate に書くと、押した瞬間を取りこぼします。

フレームに依存しない移動を書くときは、経過時間 Time.deltaTime を掛けます。掛け忘れると「速い端末ほど速く動く」という不具合になります。

毎フレームだからこその制約

Update は1秒に数十回、オブジェクトの数だけ呼ばれます。ここでの1回の無駄が、そのまま数千回の無駄になります。

  • GetComponent や Find を Update の中で呼ばない — 検索処理です。Start で取得して保持します
  • 毎フレームのメモリ確保を避ける — 一時オブジェクトを作り続けると、ガベージコレクションが走ってカクつきの原因になります
  • オブジェクトの生成・破棄を繰り返さない — 弾丸のように大量に出るものは、あらかじめ作って使い回します(オブジェクトプール)

「動く」と「滑らかに動く」の差は、ほぼこの3点に集約されます。 [[Webパフォーマンス最適化]] で「毎フレームの処理を軽くする」考え方が出てくるのと同じ発想です。

状態をどこに持つか

規模が大きくなると、スコア・所持品・進行度をどこに置くかが問題になります。

  • シーンを跨ぐと GameObject は消える — 場面転換で破棄されます
  • どこからでも触れる置き場を作ると、依存が全方向に広がる — 変更の影響範囲が読めなくなります

[[状態管理]] の考え方はここでも同じで、「誰が持ち、誰が読み、誰が書くか」を先に決めます。[[デザインパターン]] のうち、状態遷移(State)とオブジェクト生成(Factory)がゲーム開発で特に頻出するのはこのためです。

初学者向けポイント

  • シーンの保存を忘れる — 実行中に加えた変更は再生を止めると消えます。実行中の編集は「試すため」と割り切ります
  • ビルド対象を早めに決める — PC・スマートフォン・[[WebAssembly]] で使える機能と性能が違います。後から変えると作り直しが出ます
  • バージョン管理では大きなバイナリを扱う — 画像や音声が入るため、Git の大容量ファイル用の仕組みを最初に入れておきます

関連技術とのつながり

  • [[C#/.NET]] — スクリプトの記述言語。文法はWebバックエンドと共通
  • [[デザインパターン]] — State と Factory がゲームロジックで頻出する
  • [[状態管理]] — シーンを跨ぐデータの持ち方は同じ問題を扱う
  • [[WebAssembly]] — ブラウザ向けビルドの出力先
  • [[Webパフォーマンス最適化]] — 毎フレームの処理を軽くする発想が共通
Q: Unityで物理演算に関わる操作を書くべきメソッドはどれ?
- [ ] `Update`(毎フレーム呼ばれる)
- [x] `FixedUpdate`(一定間隔で呼ばれる)
- [ ] `Start`(生成時に1回)
解説: `Update` に書くとフレームレートの違う端末で挙動が変わります。逆に入力検出は `Update` に書かないと取りこぼします。

Q: GameObjectの設計モデルとして正しいのはどれ?
- [ ] 「プレイヤー」という型を継承して作る
- [x] 空の入れ物にコンポーネントを組み合わせて振る舞いを作る
- [ ] シーンごとに1つだけ存在する
解説: 継承ではなく組み合わせで作ります。同じ構成を繰り返すときはPrefabとして保存します。

Q: `Update` の中で `GetComponent` を呼ぶべきでない理由はどれ?
- [ ] 戻り値が毎回変わるから
- [x] 検索処理であり、毎フレーム×オブジェクト数だけ実行されて負荷になるから
- [ ] コンパイルエラーになるから
解説: `Start` で取得して保持します。毎フレームのメモリ確保やオブジェクトの生成・破棄も同じ理由で避けます。