AIを使ったゲーム制作

# はじめに
生成系AIの登場は、ゲーム制作にも影響しています。この記事は、2024年にゲームを個人開発した際にどのようにAIを利用したかを振り返ってみます。

## 開発環境
Unity 2022.3 で C#。先人の資産が大きい領域なので、AIはその能力を十分に発揮してくれそうです。サービスは

- OpenAI
- Claude

を使用、どちらも課金しています。この記事ではモデル個別の能力については触れませんが、おおよそ一般的にAIを利用する環境で再現できるはずです。
主にCursorを使用、Copilot は使っていません。

## 制作したゲーム

[アングル・エクスプローラー](https://www.cdddr.com/AngleExplorer/Play)
このままブラウザでプレイ可能、無料で最後まで遊べます。オートセーブ機能を入れてあるので中断も可。制作期間は２週間と少し。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90046/b53aa721-d937-dd16-1422-6326def278fd.png)


## 使用例

### その１・通常のコーディング

Cursor経由で適宜AIに尋ねながらコーディングしました。AIにコードを書いてもらってもけっきょく内容を確認することになるので、AIが正しくても間違っていても大差ありませんね、実は。
ほとんどのケースでコンパイルが通る記述を用意してくれるので、リファレンスマニュアルなどでAPIを調べる手間は大きく省けます。

#### 依頼の工夫
主に日本語で依頼するのですが、自然言語が面倒に思えるケースも多いです。ちょっとした工夫として、

```C#
_menuPanel.rect_transform.position.x = 0f;
```

こんな正しくないとわかっているコードをわざと書いておいて、

```prompt:prompt
fix this
```
と依頼しました。すると

```C#
var rectTransform = _menuPanel.GetComponent<RectTransform>();
rectTransform.anchoredPosition = new Vector2(0f, rectTransform.anchoredPosition.y);
```
これを提案してくれて、見事に気持ちを汲んでくれました。anchoredPosition というプロパティを選択する労力を考えるとありがたい限りですし（そんなのがあるのを忘れていた）、自然言語を最小限に抑えることでより効率よくコーディングできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90046/bfa2b8d2-b8cc-3745-6f76-e81b5f8f6774.png)
Cursor 上ではこんな感じ。


### その２・バグを発見する

開発中に動作がおかしかったので調査したところ、
p1
と記述すべき箇所を
p0
と間違えていることに気づきました。問題を発見したあとではあったのですが、AIの能力を試すため、修正前の状態にしたファイル全体に対して

```prompt:prompt
このコードのバグを見つけてください
```
と頼んでみたところ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90046/9767255e-9eda-03f1-d41e-1e7806e48285.png)

２. でズバリこの問題を指摘してくれています。なかなかの感動です。
以後、ときおり
```prompt:prompt
問題点を指摘して
```
と雑に依頼してコードをレビューしてもらいました。ただし的外れな指摘もけっこうあって、時間の無駄と感じることもありました。

### その３・コードネームを作成する

今回のゲームはパズルゲームですが、問題数が増えてくるとインデクスでの問題の管理が非効率になってきます。よってパズルのそれぞれにコードネームを振ることにしました。名前をつけてしまえば、問題の順番を変更するなどのゲームデザインが容易になりますよね。

```prompt:prompt
動物の名前を英語で30個並べてください。空白を含むものを除外して一単語
の動物だけでお願いします
```
結果：
> cat dog cow pig fox lion tiger bear wolf horse shark whale sheep goat mouse rat bat fish snake frog toad deer swan crow duck hawk owl finch mule lark

こういうのはAIの得意とするところで、とても有効です。ゲームが完成した現在も、これらは内部のコードネームとして使用されています。

### その４・画像素材を作成する

UIの素材やパーティクルのテクスチャなどなどで、シンプルな円などの画像を望んだ解像度で欲しくなります。アルファ値でアンチエイリアスをかける（＝周囲をぼかす）なども状況に応じて必要なので細かい作業が必要になるのですが、これもAI生成のプログラムの得意分野と言えるでしょう。私の場合は専ら python で依頼します。

```prompt:prompt
python で画像を出力する。サイズは256x256、背景は透明、半径100で
太さが8の円、その内側は白い円で塗りつぶす
```
さらにいくつかの修正依頼を重ねます。
```prompt:prompt
半径を110にして太さを16に
```
```prompt:prompt
書き出す直前に高品質な縮小アルゴリズムで縮小し、64x64の画像を出力
```

などなど。数値の変更などはコードを直接編集したほうが早いのですが、のちのち修正依頼を追加することを考慮すると、なるべくAIとのやり取りのコンテキストを残すようにしたほうが良いことも多いです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90046/14c87db0-d134-da7d-2506-b20e54f2e565.png)

この手の作業は依頼する頻度が高く、またコードを保管しておく意味もありません。なのでAIが作成したコードを即座に実行できるよう、クリップボードのコードをpythonで実行できる環境を用意しました。実に便利なのでおすすめです。
危険なコードをAIが出力する可能性もないわけではないので、注意が必要ですが。

### その５・エディタ拡張を作成する

シーン上に100個程度ある SpriteRenderer　に、８種類のスプライトをランダムにアサインしたくなりました。とても手作業ではやってられません。こういう場合はUnityの機能であるEditor拡張の出番です。

```prompt:prompt
Unityのhierarchyから複数のImageオブジェクトを選択し、それらの
sprite に複数のspriteからランダムに assign したい
```

一発で完全なエディタ拡張コードを作ってくれました。恐ろしい。すごい未来に生きているなあ、と感じます。
ゲームの実装ではないのでパフォーマンスを気にする必要もありませんし、実行結果さえ正しければいいので、コードを詳細に確認することありません。

### その６・数学的な問題を解いてもらう（失敗例）

https://x.com/dsedb/status/1816782081059615013

数学の結果をプログラムで使用する場合、使用条件にあった形式での解が必要になりますが、現在のAIにそこまでわかってもらうのは難しいですね。さほど高度でもないベクトルの計算でしたが、この件に関してはAIと格闘した時間が完全なる徒労となりました。

### その7・NativeContainerを使用する（失敗例その２）

このゲームでは mesh における vertices や triangles を動的に作成しており、作業開始時は Array を使っておいて、のちのち　NativeContainer に変更する予定で作業していました。変更するのはメモリ効率のためです。

開発が中盤を過ぎてパフォーマンスを確認するフェーズに入り、頃合いをみて Cursor 経由でコードの修正を依頼しました。

```prompt:prompt
Arrayの生成・破棄の頻度が高くガベージコレクションを発生させるので、
確保済みのメモリを使い回すように NativeList を使用する記述に
書き換えて
```
しかしながら、出力されたコードは
「コンパイルも通るし実行も可能だが、バグがある！」
というものでした。すぐに気がついたので、コードを採用した上で修正しました。具体的には、前のフレームの頂点列がゴミとして残ってしまうバグでした。
間違いが含まれていてもなお、自分で書くよりは作業効率が良いというのがまた難しいところです（なので失敗例でもないのですけど）。

# まとめ

#### 生成AIの恩恵をもっとも受けているのは
プログラマではないか、という気がしています。特にコードレビューの能力を有する人間に、より顕著なのではないでしょうか。いったんこの開発スタイルになってしまうと、もういままでの作業には戻れません。まる１日かかると思って始めた作業が午前中で終わってしまう、なんてこともありました。
「この30年ぐらい徒歩で移動していたけど、ある日突然自転車を入手した」
という感覚がもっとも近いように思います。

#### もちろん難しさもあって
AIに頼んで上手くいかなかった場合に
「頼み方が悪い」
のか
「そもそも困難な依頼だった」
のかが判然としないことがよくあります。諦めて自分の手を動かすケースも多く、
「AIがプログラムを書いてくれる」
という状態ではまったくないし、AIが書いた内容を検証するために調べる、という作業も必要になります。このバランスが難しい。常に作業効率が上がるわけではないので、どこで見切るかが重要になってきそうです。

#### 仕事を奪われる

って気はぜんぜんしないのですけど。どちらかというと、高まった能力値がよくわからなくて、作業量の見積もりが困難になっている気がします。

#### まあだいたいみんな似たようなことをしているんでしょう
けど、具体例があったほうが知見も深まるでしょうから、２０２４年8月の実例ということで紹介してみました。