現在、Unityで9x9路盤で、人とコンピューターが対戦する囲碁ゲームをつ
くりスマホで配布する、という最終目標をもっている。
今回は、その手始めとして、人対人のリバーシゲームをUnityでつくった。Unityに詳しくないぼくは、以前の経験
(https://qiita.com/tkoji3744/items/08b71054dfba4f93f2c4 )
にならい、ChatGPTに全面的に助けてもらった。
できあがったのは、
このUnityのHierarchyは下記のよう。
*そのComponentと、その後の[ ]はいわゆる「アウトレット接続」)
Main Camera
Line Prefab
(そのComponent: Transforn, Line Rendere[LineMaterial])
GoBoard
(そのComponent: Transform,
#スクリプトGo Board Generator[LinePrefab]
#スクリプトReversi game
[BlackStonePrefab, WhiteStonePrefab, ResultText])
Canvas----Result Test
そして、ゲーム上でクリックするたびに、EventSystem下に刻々とあらわれる、WhiteStone(clone), BlackStone(clone)
けっこう、いろいろなところでつまずいて、総制作時間は6時間近くを要した。
特に躓いたのは:
1. リバーシの盤面作成
提案されたのは、①外部あるいはChatGPTでつくったPNP画像を用意し、それとUnityの座標を一致させる②座標から盤面をつくる、のいずれか。最初、ChatGPTに碁盤のPNP画像をつくってもらったが、何度くりかえしても、下記のようなおかしな画像しか彼はつくれない。プログラムを書く卓越した能力にくらべるとChatGPTが絵を描く力はいまひとつのよう。
結局、ネット上の素材集から画像をとってきたが、次の「画像の線と座標を一致させる」ことが至難の技で、結局②のやり方をすることでうまく行った(GoBoardオブジェクトにアタッチされたC#スクリプトコンポーネントGo Board Generator)。
とはいえ、盤面の枠内に石をおくのか?、盤面の交点に石をおくのか?に関してGoBoardオブジェクトのC#スクリプトコンポーネントReversi game内ののvoid InitializeBoard()メソッドの数回の書き換えが必要だった。とりあえず、このスクリプトの書き換えで、石を枠内にも交点にも選んでおけるようになり、今回のリバーシ(枠内に石を置く)作成だけでなく、将来の囲碁ゲーム(交点に石を置く)作成のステップにもなった。
2. リバーシの石がひっくりかえらない。
GoBoardオブジェクトのC#スクリプトコンポーネントReversi gameは220行におよぶ。
最初、実際のゲームをすると、黒ではさむと白はひっくりかえるが、白ではさむと黒はひっくりかえらなかった。
今までの経験では、ChatGPTにこのような不具合を伝えると、あらたなスクリプト(今回の場合C#スクリプトコンポーネントReversi game)を作ってくれてその差し替えで問題はあっさり解消されるのだった。しかし、今回、何度も何度も、伝えても改善はしなかった。すると、ChatGPTから、Debug.Logの作成を提案してきて、それにそってDebug.Logの作成→その状態をChatGPTに伝達、を何回くりかえすことでようやく不具合が解消された。この、ChatGPTから、Debug.Logの作成を提案されたのははじめてだった(彼も、万能でない?)
C#スクリプト Reversi gameの全文はここで表示しないが、大枠を記すと、
using UnityEngine;
using TMPro; // TextMeshProを使用
public class ReversiGame : MonoBehaviour
{
public int gridSize = 8; // グリッドサイズ
public float cellSize = 1.0f; // 1マスのサイズ
public GameObject blackStonePrefab; // 黒石のPrefab
public GameObject whiteStonePrefab; // 白石のPrefab
public TextMeshProUGUI resultText; // 勝敗表示用のUI
private int[,] board; // 盤面の状態 (0: 空, 1: 黒, 2: 白)
private GameObject[,] stoneObjects; // 盤面上の石のオブジェクト
private bool isBlackTurn = true; // 黒石のターン
使用されているメソッドは、
void Start()
void InitializeBoard()
void Update()
void PlaceStone()
// 無効な手の場合、ターンを切り替えない
// 石を配置
// 石をひっくり返す
// ターン切り替え
// ゲーム終了判定
void PlaceStoneVisual(int x, int y, int stoneType)
// 既存の石を削除
// 新しい石を配置
bool CanPlaceStone(int x, int y)
bool CheckDirection(int x, int y, int dx, int dy, int opponent)
void FlipStones(int x, int y)
void FlipDirection(int x, int y, int dx, int dy)
bool IsGameOver()
void ShowGameResult()
}
なお、最後に、ゲーム終了後に石の数を計算して、勝敗をUI(UserInterface)で表示する機能を追加したのだが、この工程は、思ったよりスムーズにいった。
前回Qiita記事のように
( https://qiita.com/tkoji3744/items/9cde4909de312596aecb )
このUnity2022.3Versionには最初からTextMeshProがインポートされているのも、幸いしたかもしれない。