ANTIGRAVITY LABEN
記事一覧/アプリ開発
アプリ開発/2026-03-10中級

Unity × Antigravity でゲーム開発 — AI に任せて伸びる工程、手で書くべき工程

Unity で Antigravity を使い、どこまで AI に任せられるかを実際のコードで検証します。プレイヤーコントローラ・敵の状態機械・シェーダーの叩き台・Update 内のアロケーション調査まで、効く工程と効かない工程を具体例で切り分けます。


個人開発でアプリを長く運用してきた延長で、空き時間に Unity の小さなゲームを作り直しています。普段は Dolice Labs の技術サイトを書く道具として AI を使っていますが、ゲーム開発となると勝手が違いました。そこへ Antigravity を持ち込んでまず感じたのは、「全部やってくれる」でも「何も使えない」でもなく、工程ごとに得手不得手がはっきり分かれる、ということでした。

ここでは「Unity で AI が便利」という抽象論ではなく、私が実際に投げたプロンプトと返ってきたコード、そして手で直した箇所をそのまま並べます。任せて伸びる工程と、人が書いたほうが速い工程の線引きが、この記事の主題です。

プレイヤーコントローラは「8割」で返ってくる

最初の一歩として定番のプレイヤー移動を頼みました。プロンプトは「WASD で移動し、スペースでジャンプ。可変ジャンプ(押している時間でジャンプ高さが変わる)と、足元の接地判定を入れた CharacterController 用のスクリプト」。返ってきたのがこれです。

using UnityEngine;
 
[RequireComponent(typeof(CharacterController))]
public class PlayerController : MonoBehaviour
{
    [SerializeField] float moveSpeed = 6f;
    [SerializeField] float jumpForce = 7f;
    [SerializeField] float gravity = -20f;
    [SerializeField] float jumpCutMultiplier = 0.5f; // 早離しで上昇を減衰
 
    CharacterController cc;
    Vector3 velocity;
 
    void Awake() => cc = GetComponent<CharacterController>();
 
    void Update()
    {
        bool grounded = cc.isGrounded;
        if (grounded && velocity.y < 0) velocity.y = -2f; // 接地時は床に押し付ける
 
        float x = Input.GetAxisRaw("Horizontal");
        float z = Input.GetAxisRaw("Vertical");
        Vector3 move = transform.right * x + transform.forward * z;
        cc.Move(move.normalized * moveSpeed * Time.deltaTime);
 
        if (grounded && Input.GetButtonDown("Jump"))
            velocity.y = jumpForce;
 
        // ジャンプボタンを早く離したら上昇を切る = 可変ジャンプ
        if (Input.GetButtonUp("Jump") && velocity.y > 0)
            velocity.y *= jumpCutMultiplier;
 
        velocity.y += gravity * Time.deltaTime;
        cc.Move(velocity * Time.deltaTime);
    }
}

骨格は問題ありません。可変ジャンプを「ボタンを離した瞬間に上昇速度を減衰させる」方式で実装している点も、素直で読みやすい書き方です。

ただし、そのままだと斜め移動が move.normalized で正規化されているのに transform.righttransform.forward を足しているため、カメラを傾けると意図とずれます。私の用途ではカメラ相対の移動が欲しかったので、入力ベクトルを「カメラの向きに投影してから正規化」する一手間を足しました。AI は「CharacterController で動く形」までは出しますが、そのゲーム固有のカメラ設計までは読めません。ここが「8割で返ってくる」の中身です。

敵 AI は「状態機械の骨組み」を任せると速い

敵の挙動は、ゼロから書くより骨組みを出させてから埋めるのが効率的でした。「パトロール→プレイヤー検出→追跡→見失ったら最後の地点へ→一定時間でパトロールに戻る、を enum の状態機械で」と頼むと、分岐の取りこぼしが少ない雛形が出ます。

public enum EnemyState { Patrol, Chase, Investigate }
 
public class EnemyBrain : MonoBehaviour
{
    [SerializeField] float sightRange = 12f;
    [SerializeField] float loseSightAfter = 3f;
    EnemyState state = EnemyState.Patrol;
    float lostTimer;
    Vector3 lastSeen;
 
    void Update()
    {
        bool canSee = CanSeePlayer();
 
        switch (state)
        {
            case EnemyState.Patrol:
                Patrol();
                if (canSee) state = EnemyState.Chase;
                break;
 
            case EnemyState.Chase:
                ChasePlayer();
                if (canSee) { lastSeen = PlayerPos(); lostTimer = 0; }
                else { lostTimer += Time.deltaTime;
                       if (lostTimer > loseSightAfter) state = EnemyState.Investigate; }
                break;
 
            case EnemyState.Investigate:
                MoveTo(lastSeen);
                if (canSee) state = EnemyState.Chase;
                else if (ReachedLastSeen()) state = EnemyState.Patrol;
                break;
        }
    }
}

ここで効くのは、人間が忘れがちな「見失った後の振る舞い」を AI が先に枠として用意してくれる点です。CanSeePlayer()Patrol() の中身は、レイキャストの層設定やナビメッシュの有無といったプロジェクト固有の事情に依存するので、結局は自分で書きます。骨組みは AI、中身は人、という分担が一番噛み合いました。

シェーダーは「叩き台まで」が現実的な期待値

被ダメージ時の赤フラッシュのような、よくあるエフェクトは Antigravity に下書きを出させると時短になります。「URP の Shader Graph ではなく、HLSL で被ダメージ時に色を白〜赤へ寄せる簡単なフラグメント」を頼んだ結果がこちらです。

// 簡易ヒットフラッシュ(_FlashAmount を 0→1 で制御)
fixed4 frag (v2f i) : SV_Target
{
    fixed4 col = tex2D(_MainTex, i.uv);
    fixed3 flash = lerp(col.rgb, fixed3(1, 0.2, 0.2), _FlashAmount);
    return fixed4(flash, col.a);
}

考え方としては十分です。ただ、シェーダーは Unity のレンダーパイプライン(Built-in / URP / HDRP)によって書き方も変数名も変わります。AI は指定したパイプラインを取り違えることがあり、URP と書いても Built-in 前提のコードが混ざることがありました。私は「叩き台をもらって、自分のパイプラインに合わせて直す」前提で使っています。シェーダーを丸ごと信頼するのは、まだ早いというのが正直な感触です。

パフォーマンス調査こそ、AI が本領を出す

意外だったのは、コード生成よりもボトルネックの当たりをつける用途のほうが頼りになったことです。「Update が重い。フレームレートが落ちる」という曖昧な相談でも、Antigravity は典型的な容疑者から順に挙げてくれます。

たとえば私のコードでは、Update の中で毎フレーム GetComponent を呼んでいた箇所と、new でリストを作り直していた箇所を指摘されました。前者はキャッシュ、後者は使い回しに直すだけでアロケーションが消えます。

// Before: 毎フレーム GetComponent + 新規リスト = GC を生む
void Update() {
    var rb = GetComponent<Rigidbody>();
    var hits = new List<Collider>(Physics.OverlapSphere(transform.position, 3f));
    // ...
}
 
// After: 参照はキャッシュ、バッファは使い回す
Rigidbody rb;
readonly Collider[] buffer = new Collider[16];
void Awake() => rb = GetComponent<Rigidbody>();
void Update() {
    int n = Physics.OverlapSphereNonAlloc(transform.position, 3f, buffer);
    // ...
}

OverlapSphereNonAlloc のような「アロケーションを生まない API」へ寄せる提案は、公式リファレンスを読み慣れていないと出てこない発想です。私はプロファイラで赤くなった原因が分からないとき、まず Antigravity に状況を説明して当たりをつけ、それから Unity Profiler で裏を取る、という順番にしてから調査が速くなりました。

逆に、AI に任せて伸びなかった工程

正直に書くと、効かない工程もはっきりあります。

ひとつは「ゲームの手触り(ゲームフィール)」です。ジャンプの気持ちよさ、ヒットの重み、カメラの追従の柔らかさといった数値は、実際に動かして自分の指で確かめるしかありません。AI に「気持ちよくして」と頼んでも、それは自分が遊んで決める領域でした。

もうひとつはシーン構成とプレハブ設計です。どのオブジェクトを親子にし、どこをプレハブに切り出すかは、そのゲームの拡張方針に強く依存します。ここを AI 任せにすると、後から手を入れにくい構造になりがちでした。設計の意思決定は人が握り、その実装の手数を AI に渡す、という線引きに落ち着いています。

次の一歩

もしこれから Unity に Antigravity を入れるなら、いきなり大きな機能を頼まず、プレイヤーコントローラのような「正解が見えている小さな課題」で一度試すことをおすすめします。返ってきたコードのどこを直したかをメモしておくと、自分のプロジェクトで AI が読み取れない前提(カメラ設計・パイプライン・命名規約)が見えてきます。その境界が分かれば、任せる工程と手で書く工程の判断が一気に速くなります。

シェア

お読みいただきありがとうございます

Antigravity Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

アプリ開発2026-07-18
iOS 27 パブリックベータをどの端末に入れるか — 検証機の決め方と、戻れない前提での備え
iOS 27 のパブリックベータが 7/13 に公開されました。ビルド番号が開発者向けベータ3と同一である事実を起点に、どの端末に入れるか、入れる前に何をアーカイブするか、アプリのどこから確認するかを個人開発の視点で整理します。
アプリ開発2026-07-18
「Compose ファースト」の後で、View の画面をどの順に移すか — 画面数ではなく変更頻度で決める
Google が Android 開発を Compose ファーストと表明しました。View ベースの画面をどの順で移すかを、画面数ではなく git の変更履歴から決める判断軸と、実際に動かしたスコアリングスクリプトをまとめます。
アプリ開発2026-07-17
Android 17 のローカルネットワーク権限 — LAN に触る箇所を機械で洗い出してから、エージェントに直させる
新しい API レベルではローカルネットワークへの明示的な許可が必要になります。grep では 11 経路のうち 2 つしか見つかりませんでした。経路の種類で拾う検出器と、エージェントに渡せる作業単位への畳み方を実測とともに。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →