話題のChatGPTでAIにゲームを作ってもらいたい (前編) [Unity]

(22/12/06 09:16追記)
記事当日から見て明日に更新しなかったため、記述を修正
記事の構成が変更になったため、記述を修正

ChatGPTにゲームを作ってもらう話を<del>前後編で</del>書きます。

# はじめに
OpenAIが発表した対話型AI「ChatGPT」がすごいと今話題になっているようです。
[https://chat.openai.com](https://chat.openai.com)
ChatGPTはGPT-3(3.5)という言語モデルをベースとしたサービスで、テキストチャット形式で質問や会話に自然に答えてくれます。
話題になっているのは恐らくその受け答えの自然さの他にも、例えば数学の証明や歴史上の出来事の説明などでたまに頓珍漢な回答を返すおかしさなどによるところもあると思いますが、その他にもう一つ、要求した仕様に合わせたコード生成を行ってくれるというところも面白いところです。
コードの自動生成を行ってくれるAIは以前からGitHub Copilot(これも開発にOpenAIが関わっているらしいです)などがありましたが、ChatGPTは対話形式でコードを教えてくれるので、まるで職場の先輩に質問しているような気分になります。
自分も試しに使ってみたところ、かなりの精度でスクリプトの実装が返ってきて驚きました。
以下は、「ゲームエンジンUnityで、CharacterControllerを使ってプレイヤーを動かすスクリプトを書いてください。」と聞いたときの返答です。
![sample_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2987563/32418484-8921-5ceb-4ac2-f90b1384967e.png)
`InputManager`や`CharacterController`を適切に使用してユーザーが操作できるプレイヤー制御のスクリプトを実現しているようです。
この様子なら**AIにコードを書く作業を任せてしまってもゲームを作れるのではないか**、というのがこの記事の趣旨になります。
なおなるべくChatGPTの言うことを聞いて作るつもりですが、どうしてもChatGPTではできなかった部分は自分で書く場合があります。
その場合は自分で書いた旨を明記しますので、ご了承ください。

# コードがちゃんと動くか確認
どんなゲームを作るか早速決めていきたいところですが、まず先程生成してもらったコードが実際に動くものであるか実行して確かめます。見た感じは大丈夫そうでしたがどうでしょうか？

![move_test.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2987563/728b35d7-31db-4b86-ef76-aada658d818d.gif)

先ほどのスクリプトをアタッチしましたが、問題なく動くようです。

# どんなゲームを作るか
どんなゲームを作るかもChatGPTのいうことを参考にしようと思いましたが、
![スクリーンショット 2022-12-03 21.04.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2987563/827ed72f-7077-17de-dbbf-3a0eee71a037.png)
ゲームをプレイしないようで、好みを聞くことはできませんでした。
なので月並みではありますが、**FPSゲームを作ってもらう**ことにしました。

# FPSの作り方を聞いてみる
もしかしてChatGPTは作り方という大枠を聞いても答えてくれるのでしょうか？
ダメ元で聞いてみます。
![スクリーンショット 2022-12-03 22.08.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2987563/3f5e422b-fc56-8533-67b9-4409d1587bc2.png)
**教えてくれました。**
この後何回か回答が途切れてしまいましたが「続きを書いてください」とお願いすることで、`FirstPersonController`、`WeaponController`、`EnemyController`の3つのスクリプトのコードを教えてもらうことができました。
以下に内容を記載します。
## FirstPersonController
```CS:FirstPersonController.cs
using UnityEngine;

public class FirstPersonController : MonoBehaviour
{
    // プレイヤーキャラクターの Rigidbody
    public Rigidbody playerRigidbody;

    // マウスの移動量
    private Vector3 mouseMovement;
    
    // プレイヤーキャラクターの移動速度
    public float speed = 10.0f;
    
    // Use this for initialization
    void Start ()
    {
        // Rigidbody コンポーネントをキャッシュしておく
        playerRigidbody = GetComponent<Rigidbody>();
    }
    
    // Update is called once per frame
    void Update ()
    {
        // マウスの移動量を取得する
        mouseMovement = new Vector3(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y"), 0.0f);
    
        // マウスの移動量を元に、カメラの Transform を更新する
        transform.Rotate(-mouseMovement.y, mouseMovement.x, 0.0f);
    }
    
    void FixedUpdate()
    {
        // キーボードの入力を元に、プレイヤーキャラクターを移動する
        float moveHorizontal = Input.GetAxis("Horizontal");
        float moveVertical = Input.GetAxis("Vertical");
        Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical);
        playerRigidbody.AddForce(movement * speed);
    }
```
### ChatGPTの説明
![スクリーンショット 2022-12-03 22.15.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2987563/f588b2b2-bd29-e2ac-f263-96bfded8eb4c.png)

## WeaponController
```CS:WeaponController.cs
using UnityEngine;

public class WeaponController : MonoBehaviour
{
    // 武器のプレハブ
    public GameObject weaponPrefab;

    // 発射する弾丸のプレハブ
    public GameObject bulletPrefab;

    // 弾丸の発射位置
    public Transform firePosition;

    // 弾丸の速度
    public float bulletSpeed = 1000.0f;

    // 弾丸の発射間隔
    public float fireInterval = 0.1f;

    // 発射した弾丸の数
    private int shotCount;

    // Update is called once per frame
    void Update ()
    {
        // マウスの左クリックが押された場合
        if (Input.GetMouseButtonDown(0))
        {
            // 弾丸を発射する
            Fire();
        }
    }

    // 弾丸を発射する
    void Fire()
    {
        // 弾丸の発射間隔が経過している場合のみ発射する
        if (Time.time > fireInterval + shotCount * fireInterval)
        {
            // 弾丸のプレハブからインスタンスを生成する
            var bullet = Instantiate(bulletPrefab, firePosition.position, firePosition.rotation);

            // 弾丸に力を加えて発射する
            bullet.GetComponent<Rigidbody>().AddForce(firePosition.forward * bulletSpeed);

            // 発射した弾丸の数をカウントアップする
            shotCount++;
        }
    }
}
```

### ChatGPTの説明
![スクリーンショット 2022-12-03 22.21.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2987563/85811841-ff89-85ff-2f1c-963f55389a68.png)

## EnemyController
```CS:EnemyController.cs
using UnityEngine;

public class EnemyController : MonoBehaviour
{
    // プレイヤーキャラクター
    public Transform player;

    // 敵キャラクターの移動速度
    public float speed = 10.0f;

    // 敵キャラクターの射程
    public float attackRange = 10.0f;

    // 敵キャラクターの攻撃間隔
    public float attackInterval = 1.0f;

    // 敵キャラクターが攻撃したかどうか
    private bool attacked;

    // Update is called once per frame
    void Update ()
    {
        // プレイヤーキャラクターとの敵キャラクターとの距離を計算する
        var distance = Vector3.Distance(transform.position, player.position);

        // プレイヤーキャラクターが近づいている場合
        if (distance < attackRange)
        {
            // プレイヤーキャラクターに向かって移動する
            var direction = player.position - transform.position;
            transform.Translate(direction.normalized * speed * Time.deltaTime);
            // 敵キャラクターが攻撃していない場合
            if (!attacked)
            {
                // 敵キャラクターを攻撃する
                Attack();
    
                // 敵キャラクターが攻撃したことを記録する
                attacked = true;
            }
        }
        else
        {
            // 敵キャラクターが攻撃していないことを記録する
            attacked = false;
        }
    }
    
    // 敵キャラクターを攻撃する
    void Attack()
    {
        // 攻撃間隔が経過している場合のみ攻撃する
        if (Time.time > attackInterval)
        {
            // ここに攻撃の処理を記述する
            Debug.Log("Enemy attacked!");
        }
    }
}
```

### ChatGPTの説明
![スクリーンショット 2022-12-03 22.24.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2987563/40185847-3cd6-fd4f-3241-99e9ff4f7d32.png)

ChatGPTの説明を聞くだけで3つのスクリプトが完成してしまいました。

# 次回
自分が想像していたよりもかなりわかりやすく書いてもらえました。
<del>次回(明日)は実際にこのコードを使ってゲームを組み立てていこうと思います。</del>

ChatGPTにプログラムを修正してもらう話を書きました。

https://qiita.com/tanikura/items/5bf34d8ad29b1f0fb703