【ChatGPT】AIにUnityで大人気色塗りゲームを作る方法を聞いてみた(AIコード生成)

# はじめに
ChatGPTという対話AIで某色塗りゲームのコードを生成してみました。動くかはまだ検証できてません。

AIの回答が途中で途切れたり、的はずれな内容が出てくることもあったので随時質問をして出てきた答えをいい感じに繋げたものとなります。途中で途切れた場合は、「続きを教えて」というと教えてくれます。

送られてきた文章は、ほぼ内容を変えずに貼っています。
# 答え その1
Unityでインクを発射して塗る機能を実装するには、まずは「プレイヤー」オブジェクトを作成します。次に、「インク」オブジェクトを作成して、プレイヤーから発射するようにします。


「プレイヤー」オブジェクトから「インク」オブジェクトを発射するには、「Projectile」という名前のスクリプトを追加します。このスクリプトは、「Fire」という名前のメソッドを実装します。このメソッドは、「プレイヤー」オブジェクトが「インク」を発射するときに呼び出されます。

```c#:Projectile
// Projectileスクリプト
using UnityEngine;

public class Projectile : MonoBehaviour
{
    public GameObject inkPrefab;

    public void Fire()
    {
        GameObject ink = Instantiate(inkPrefab, transform.position, transform.rotation);
        ink.GetComponent<Rigidbody>().AddForce(transform.forward * 10, ForceMode.Impulse);
    }
}
```
「Fire」メソッド内では、「インク」オブジェクトを作成して、「プレイヤー」オブジェクトから発射するようにします。「インク」オブジェクトは、RigidbodyとColliderコンポーネントを持つ必要があります。Rigidbodyコンポーネントを使用することで、「インク」オブジェクトを物理的に正確に振る舞わせることができます。Colliderコンポーネントを使用することで、「インク」オブジェクトが物理的に接触するオブジェクトと衝突することができるようになります。



次に、「インク」オブジェクトにスクリプトを追加します。このスクリプトは、「OnTriggerEnter」という名前のメソッドを実装する必要があります。このメソッドは、「インク」オブジェクトが他のオブジェクトと衝突した時に呼び出されます。
```c#:Ink
// Inkスクリプト
using UnityEngine;

public class Ink : MonoBehaviour
{
    void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.CompareTag("Ground"))
        {
            Destroy(gameObject);
        }
        else
        {
            other.gameObject.GetComponent<Renderer>().material.color = Color.blue;
        }
    }
}
```

「OnTriggerEnter」メソッド内では、「インク」オブジェクトが衝突したオブジェクトが「地面」オブジェクトかどうかを判断します。もし、「地面」オブジェクトと衝突していた場合は、「インク」オブジェクトを削除します。「インク」オブジェクトが「地面」以外のオブジェクトと衝突した場合は、そのオブジェクトの色を変更します。

# 答え その2

質問 : UnityでFPS視点で弾代わりにインクを水鉄砲のように発射して、飛ばしたインクで絵を描く機能のコードを教えて

候補1のときよりも、詳しく作りたいゲームを書いてみました。


UnityでFPS視点でインクを発射するには、以下の手順が必要です。

1.Unityプロジェクトを作成します。
2.FPS視点を実装するために、「FirstPersonCharacter」プレハブをシーンに配置します。このプレハブは、Unityに同梱されているサンプルプロジェクト「Standard Assets」から入手できます。
3.発射するインクのプレハブを作成します。このプレハブには、発射するインクを表す「Ink」という名前のゲームオブジェクトが含まれます。
4.インクを発射するためのスクリプトを作成します。このスクリプトは、FirstPersonCharacterが持つ「InkLauncher」という名前のスクリプトコンポーネントにアタッチされます。
5.スクリプトの中で、「InkLauncher」スクリプトコンポーネントが持つ「Ink」プレハブを、「Instantiate」関数を使ってインスタンス化します。これにより、シーン上に新しいインクが生成されます。
6.生成されたインクに、「Rigidbody」コンポーネントを追加します。このコンポーネントにより、インクは物理演算に基づいて移動するようになります。
7.インクを発射するための「Fire」関数を作成します。この関数は、インクの発射方向を計算して、「Rigidbody」コンポーネントに適切な力を加えることで、インクを発射するようにします。
8.スクリプトを実行して、「Fire」関数を呼び出すことで、インクが発射されるようになります。

以上が、UnityでFPS視点でインクを発射する方法になります。実際にコードを書く際は、上記の手順に従ってスクリプトを作成していきます。

上記の手順に従って作成したスクリプトの例を示します。

まず、「InkLauncher」という名前のスクリプトコンポーネントを作成します。

```c#:InkLauncher
using UnityEngine;

public class InkLauncher : MonoBehaviour
{
    // 発射するインクのプレハブ
    public GameObject inkPrefab;

    // 発射する速度
    public float launchSpeed = 10.0f;

    // Update is called once per frame
    void Update()
    {
        // 発射するキーが押されたとき
        if (Input.GetKeyDown(KeyCode.Space))
        {
            // インクを発射する
            Fire();
        }
    }

    // インクを発射する
    void Fire()
    {
        // インクのプレハブからインスタンスを生成する
        GameObject ink = Instantiate(inkPrefab, transform.position, transform.rotation);

        // インクにRigidbodyコンポーネントを追加する
        Rigidbody rb = ink.AddComponent<Rigidbody>();

        // インクを発射する方向を計算する
        Vector3 launchDirection = transform.forward;

        // インクに適切な力を加える
        rb.AddForce(launchDirection * launchSpeed, ForceMode.VelocityChange);
    }
}
```

以上が、UnityでFPS視点でインクを発射する方法です。上記のスクリプトを作成することで、水鉄砲のようにインクを飛ばして、絵を描くような機能を実装することができます。

さらに、飛ばしたインクで絵を描くためには、インクに色を付けることが必要です。

### 地面に色を塗る
UnityでFPS視点でインクが地面に接触したときに絵を描くには、以下の手順が必要です。

1.発射するインクのプレハブを作成します。このプレハブには、発射するインクを表す「Ink」という名前のゲームオブジェクトが含まれます。

2.「Ink」プレハブに「Renderer」コンポーネントを追加します。このコンポーネントを使って、インクに色を付けることができます。

3.「Ink」プレハブに「Collider」コンポーネントを追加します。このコンポーネントを使って、インクが地面に接触したときに処理を実行することができます。

4.「Ink」プレハブに「OnCollisionEnter」関数を実装します。この関数は、インクが地面に接触したときに呼び出されます。

5.「OnCollisionEnter」関数内で、インクが地面に接触した位置に絵を描く処理を実装します。

以上が、UnityでFPS視点でインクが地面に接触したときに絵を描く方法です。実際にコードを書く際は、上記の手順に従ってスクリプトを作成していきましょう。

例として、「Ink」プレハブに「OnCollisionEnter」関数を実装する方法を示します。

```c#:Ink
using UnityEngine;

public class Ink : MonoBehaviour
{
    // 絵を描くために使用するマテリアル
    public Material material;

    // 絵を描くために使用するテクスチャ
    public Texture2D texture;

    // 絵を描くための半径
    public float radius = 0.1f;

    // 絵を描くための色
    public Color color = Color.black;

    void OnCollisionEnter(Collision collision)
    {
        // 絵を描く位置を取得する
        Vector3 position = collision.contacts[0].point;

        // 絵を描く
        Draw(position);
    }

    // 絵を描く
    void Draw(Vector3 position)
    {
        // 絵を描くためのテクスチャを取得する
        Texture2D tex = GetTexture();

        // 絵を描くためのマテリアルを取得する
        Material mat = GetMaterial();

        // 絵を描く
        Graphics.DrawTexture(new Rect(position.x, position.y, radius * 2, radius * 2), tex, mat);
    }

    // 絵を描くためのテクスチャを取得する
    Texture2D GetTexture()
    {
        // テクスチャが設定されていない場合は、新しいテクスチャを作成する
        if (texture == null)
        {
            texture = new Texture2D(1, 1);
            texture.SetPixel(0, 0, color);
            texture.Apply();
        }

        return texture;
    }

    // 絵を描くためのマテリアルを取得する
    Material GetMaterial()
    {
        // マテリアルが設定されていない場合は、新しいマテリアルを作成する
        if (material == null)
        {
            material = new Material(Shader.Find("Unlit/Texture"));
            material.mainTexture = texture;
        }

        return material;
    }
}
```

上記の例では、「OnCollisionEnter」関数内で「Draw」関数を呼び出しています。「Draw」関数は、指定された位置に絵を描く処理を行います。

「Draw」関数では、絵を描くために「Graphics.DrawTexture」関数を使用しています。この関数は、指定された座標に指定されたテクスチャを描画します。

また、「Draw」関数内では、「GetTexture」関数と「GetMaterial」関数を呼び出しています。これらの関数は、絵を描くために必要なテクスチャとマテリアルを取得するものです。

「GetTexture」関数では、「texture」プロパティが設定されている場合はその値を、設定されていない場合は新しいテクスチャを作成して返します。「GetMaterial」関数でも同様です。

以上が、UnityでFPS視点でインクが地面に接触したときに絵を描く方法です。実際にコードを書く際は、上記の手順に従ってスクリプトを作成していきましょう。

もし、より詳細な情報が必要であれば、Unityのマニュアルやトレーニングビデオなどを参照するとよいでしょう。また、Unityには様々なサンプルプロジェクトが同梱されているため、それらを参考にすることもできます。


# まとめ
軽く遊んで思ったのは、俺完全敗北。ズタボロです。
エンジニアの仕事がAIに奪われてしまう日も近いかもしれません。ブラボー！！！

# 追記: 答え その2をやってみました
<iframe width="560" height="315" src="https://www.youtube.com/embed/6w8mdKaQwT8" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

球を打つコードは問題なく動作しました！若干、打たれる方向がおかしくなるときがありますがエラーなく動いたのは凄いですね。調整すればいい感じになりそうです。
ちなみに、StandardAssetsのインポートでエラーが出ると思うので、以下の記事を参考にコードを改変してみてください。
https://nekojara.city/unity2020-standard-assets

<iframe width="560" height="315" src="https://www.youtube.com/embed/mc6kibfG9TE" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

色を塗る機能はうまくいきませんでした。色自体は変わるものの、マテリアル全体の色が変わってしまってだめでした。テクスチャのあるオブジェクトを指定しても上手くいきませんでした。コード自体に問題があるのか、私のやり方がよくないのか不明ですが、でも惜しい点まではいっていると思うのでうまく改良すれば動きそうな気もします。

![スクリーンショット 2022-12-02 17.44.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315874/3085b41b-2458-1e24-fa00-56e367d1d92c.png)

ちなみに、テクスチャーの画像生成が1×1だったのを2×2にしたらこうなりました。おかしなところが塗られてますが、画像の向きがズレてるから...？詳しい方いたら教えて下さい...!