![見出し画像](https://assets.st-note.com/production/uploads/images/105004941/rectangle_large_type_2_cff38be88231977bb862e4c42dfed44f.png?width=1200)
[Unity]2日間ゲームジャムにて、chatgpt君にVampireSurviversっぽいゲームを吐いてもらおうとした
ので、備忘録つくります。
メンバ構成は
・プランナーさん x2
-> AIでアイデア出ししたり、レベルデザインしたり、AIでSprite用意したり。
・unity実装 x1 (私)
でした
https://www.e-topia-kagawa.jp/lecture/saikyo_game_jam_2023/
結局AIどうだった?
・ChatGPT(GPT-4)君に任せきりにすることを途中で頭から抜けちゃったので、この記事あんまし参考になんないかもです。
実装の補佐だったりひとまず土台組んでみて―っていうのは現状でもできそう。
プログラム部分を頼り切りにするのは、入力側にも技量要りそうだなって思いました。
※英語で聞いたり、「優秀なエンジニア」をロールとして与えればもっと優秀になるかも?
・Spriteとかはパッと揃えられるのはよさそうだけど、ライセンス回り不安しかないのよね…
あと絵に単語文字列を登場させるのが苦手っぽい
・アイデア出しはまあ一定やってくれそう
実装者向けメモ
・UIはUniRxのSubscribeの機能とDoTween覚えとくと結構楽になります。
HPをIntReactivePropertyとかにして、変更掛かったタイミングでUIに反映されるようSubscribeで仕込んどけばOK
・Singletonパターンでオブジェクトプール管理クラスとかUI管理クラス組んだほうが実装早いかも? 依存関係酷いことになるけど、短期ゲージャムであればそこまで影響はない
・想定プレイ時間5分は長く、二日では到底開発しきれなかった。
30秒~1分ぐらいがよさそう。
想定プレイ時間 x 1000~2000 = 開発時間
ぐらいに考えた方がいい。短いほどブラッシュアップ時間を確保できる。
・ゲージャム中に関してはSE・BGM再生周りをもう下のやつに頼り切りにしといてもよさそう。
成果物
期日タイミングだとゲーム開始から最初のボス撃破まで....ってとこで止まってました。仕様書上の2~3割ぐらいしか入ってない感じです。
ジャム終わったあとの調整でゲームっぽくしました。
1. お題発表「ひろがる」~仕様設定
今回はプランナー陣がお題をChatGptに食わせてゲーム内容を決めさせました。
<入力>
小学生が参加しているゲームジャムに参加中です。そこで制作ゲームの企画をする。
・開発期間は2日間
・Unityを使う。
・遊んでもらって評価をもらいたい対象は”参加している小学生”
・2Dのゲーム
・作業者は2名
・テーマは”ひろがる”
企画案を10案ください。
<出力>
以下は、上記の企画案から、ゲームリテラシーが高く、
小学生高学年に好まれそうな5つの企画案の概要です。
「花畑の旅」
プレイヤーは、花畑の中を旅しながら、新しい花を集め、自分の庭を広げていく。
広がっていく庭は、プレイヤーのセンスで作り込むことができ、美しい庭を作り上げることが目的。
ゲーム内での花の育成や庭づくりに必要なアイテムの収集、自由度の高い庭づくりなどが楽しめる。
「(以下略)
で、結果的に以下がチョイスされることになりました。
<出力>
「海賊船の冒険」は、プレイヤーが海賊船の船長となり、敵船とのバトルや宝物探しに挑戦しながら、
自分だけの海賊船を作り上げていくアクションゲームです。
プレイヤーは、海賊船を進めながら、敵船とのバトルや宝物探しに挑戦します。
また、海賊仲間を集めたり、船の改造なども可能であり、
自分だけの海賊船を作り上げる楽しみがあります。
ゲーム内での海賊仲間の募集や船の改造、敵船とのバトル、宝物の探索などが楽しめます。
また、プレイヤーが冒険を進めることで、新しい船や武器、
アイテムなどが手に入り、自分だけの海賊船を作り上げることができます。
~中略~
「海賊船の冒険」は、トップビューの視点で開発することが適切であると考えられます。
トップビューは、上から見下ろす視点で、海域や敵船などを広く見渡すことができます。
<入力>
テーマの回収どうすんの?
<出力>
ゲームの目的を「新しい海域を発見し、冒険の世界を広げること」として中心に据えます。
~以下略~
おいおいおい、機能もりもりやん、2日でできんのかこれ…(※できなかった)
2. (AI)実装開始のための設計
ひとまずトップビューシューターの原型を作るためChatgptくんにクラス図書かせてみました。
![](https://assets.st-note.com/img/1683453897102-JmlF21PzhO.png)
![](https://assets.st-note.com/img/1683453924282-CX8C6fOzG7.png)
ゲームマネージャー、プレイヤー、敵、玉と欲しいところは抑えていそう
3. (AI)プレイヤー実装させてみる
設計大体想像ついたんでコード書かせてみます
![](https://assets.st-note.com/img/1683454050239-fpd0MGHhqP.png)
![](https://assets.st-note.com/img/1683457729429-6dbxbw5sq0.png)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
// プレイヤーの移動速度
public float moveSpeed = 5.0f;
// 弾丸プレファブ
public GameObject bulletPrefab;
// 弾丸発射速度
public float fireRate = 0.5f;
private float nextFire;
// Update is called once per frame
void Update()
{
Move();
Shoot();
}
private void Move()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
Vector3 moveDirection = new Vector3(horizontal, vertical, 0).normalized;
transform.position += moveDirection * moveSpeed * Time.deltaTime;
}
private void Shoot()
{
if (Input.GetButton("Fire1") && Time.time > nextFire)
{
nextFire = Time.time + fireRate;
Instantiate(bulletPrefab, transform.position, Quaternion.identity);
}
}
public void TakeDamage(int damage)
{
// プレイヤーのHPを減らす処理
}
private void OnTriggerEnter2D(Collider2D other)
{
// 敵や敵の弾丸と衝突したときの処理
}
}
<気づいた点>
・コメント付き偉いね
・ちゃんと事前のクラス図出力に沿ってメソッド吐いてるね
・移動処理に関しては問題なさそう
・弾についてもおおむね問題なさそうだけど、Time.time使うのちょっと気になった。 deltaTime使っていいんじゃねえかな
・入力受け取り部分についてもInput.Get系使ってるので偉い
・private、public変数ともにロワーキャメルなのはちょっと気になりますが、まあコーディングルール指定すればいいのかな?
・コンポーネントアタッチ部分まで説明してくれてるので、初心者にはうれしそう
で、言われたとおりにアタッチしたところ、プレイヤーオブジェはいい感じに動いてくれました。
カメラ追従させたくなったので、その要望伝えたところ
![](https://assets.st-note.com/img/1683458000831-4vqbO9CK3W.png)
まあいい感じに教えてくれました。Packageのインスコ方法まで教えてくれるなんて優しいですね。従って設定したところいい感じに追従してくれました。
…..
…
他にもコード書く必要あったんだけど、ChatGPT君にお任せするってコンセプト忘れて一定自分でコーディングしちゃってました
詳細な要件来たタイミングが結構深夜になっちゃったのと、
結局実装中に必要な機能(敵とか弾のオブジェクトプールとか)思いついたりしてシームレスに追加実装とかしちゃうので。。。
ちゃんと余裕あるスケジュで実装挑んで再挑戦したいですー
補佐として使ったケースは何件かあるので記しておきます。
4. (AI/失敗)逆マスク作らせたかった
要件として、
・未開放海域の雲の中にいる間、自分の周り以外を真っ暗にしてくれ
というのが来ました。
![](https://assets.st-note.com/img/1683459507791-rjOaqHsPCj.png?width=1200)
![](https://assets.st-note.com/img/1683459525007-YvnXHkPzOL.png?width=1200)
Shader使ったら楽そうだけど、この辺りパッと書ける自信なかったので、ChatGPT君に書かせてみることにしました。
![](https://assets.st-note.com/img/1683459189047-kMsOvScMu8.png)
なんかUpdateメソッド部分で謎のposition移動やってんのは気になる。そもそもコード途中で切れてるし.…
で、ひとまず5あたりまで進めたんですが、普通にマスクしてくれないんですよね…
相談してみました。
![](https://assets.st-note.com/img/1683459665990-ve9pnxZDep.png)
うーん? Shaderあんまわからない私でも、
o.Albedo = 1 - c.rgb;
o.Alpha = c.a;
あたり、なんか的外れなことしてるのが感じられました。変えるならo.Alphaあたりっすよね...?
まあ普通に従っても意図した表示になりませんでした。
この作業やってるのが深夜4時ぐらいだったというのもあり、コードでクールに解決するのめんどくさくなりました。
顔ハメ看板よろしく適当に真ん中くりぬいた1280x720の画像用意して、それを表示/非表示切り替えるようにして代用しました。
5. (AI/失敗)矩形の判定に、プレイヤーが乗っかってる状態を取得したかった
前の項目でやってた、
・未開放海域の雲の中にいる間、自分の周り以外を真っ暗にしてくれ
の機能で、雲の中にいるかどうかって判定をChatgptにやらせてみました。
![](https://assets.st-note.com/img/1683460691426-brUsqmXsuy.png)
![](https://assets.st-note.com/img/1683462872020-nBxUhO8ktS.png)
using UnityEngine;
public class BoxCollidersController : MonoBehaviour
{
public BoxCollider2D[] boxColliders;
private int playerOnCollidersCount = 0;
public bool allCollidersActivated = false;
private void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
playerOnCollidersCount++;
if (playerOnCollidersCount == boxColliders.Length)
{
allCollidersActivated = true;
}
}
}
private void OnTriggerExit2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
playerOnCollidersCount--;
if (allCollidersActivated)
{
allCollidersActivated = false;
}
}
}
}
プレイヤーが3つのBoxCollider2Dのすべてに乗っている場合にのみ、
辺りで解釈間違ってるっぽいです。
ここ実装してるのが徹夜明け朝8時、期限まで数時間だったというのもあり、もうめんどくさくなって自分で実装しました。
6. (AI) プレイヤーと敵の位置関係をもとに角度取得する処理を書かせた
要件として、
・ボスの方向にロケーター出してほしい
ってのがあったので、これについて処理書かせました。
![](https://assets.st-note.com/img/1683463774043-XxbCu4jlXx.png?width=1200)
画面中央にロケーター表示して、プレイヤーとターゲットの位置関係をもとに0~360度回転させることによりコンパスっぽくします。
ターゲット.position - プレイヤー.positionで方向ベクトル取って、ここから角度取る方法を聞いてみました。
![](https://assets.st-note.com/img/1683464023946-xSopi8T8iU.png)
そのまま使ってもいい感じに動いてくれました。
(まあ毎フレこの計算するのちょっと負荷が怖いけどね)
7. (AI) プレイヤーレベルに応じて、弾発射数を増やさせてみた
要件として、
・プレイヤーのレベルアップに伴って出す弾増やせ
ってのがあったので、こちらもAIにやらさせてみました。
![](https://assets.st-note.com/img/1683465115063-uszCxXtqXu.png)
![](https://assets.st-note.com/img/1683464641526-VL2esBwrU4.png)
まあそのまま使えました。
前提条件として使うメソッド渡してみたのですが、それもいい感じに引数指定して使えています。
8. (AI) DoTween使ってオブジェ動かしてみた
経験値アイテムである金貨を拾うとき、一定近づいたタイミングでプレイヤーに移動させたいので、それを書かせてみました。
![](https://assets.st-note.com/img/1683465344476-cTW24CWRzj.png)
![](https://assets.st-note.com/img/1683465569343-2s1atFfvS5.png)
using UnityEngine;
using DG.Tweening;
public class MoveToObject : MonoBehaviour
{
[SerializeField] private GameObject objectToMove;
[SerializeField] private GameObject targetObject;
[SerializeField] private float duration = 1f;
private void Start()
{
MoveObjectToTarget();
}
private void MoveObjectToTarget()
{
Vector3 targetPosition = targetObject.transform.position;
objectToMove.transform.DOMove(targetPosition, duration).SetEase(Ease.Linear);
}
}
Dotweenってサードパーティのライブラリなんだけど、いい感じに使えてて偉い。
まあ結局終着点更新のため書き方変えたけど、このままでも十分使えます。
9. (AI) スマホ対応
スマホからでも遊べるようできないかという話になったので、雑に相談してみました。
![](https://assets.st-note.com/img/1683473949387-iyUPEV7KT4.png)
なんかいろいろ教えてくれましたが、バーチャルパッドだけ追加することにしました。
驚くべきことに、「Joystick Pack」ってAssetStore上にあるんですよね。今回それ入れていい感じに動きました。
以上です。
次やるならちゃんと余裕持ったスケジュール + 仕様ミニマムにして、AI頼り切りで作れないか検証したいですねー