最近、MacBook Air を購入して、色々な開発欲求が高くなってきたので、
30歳超えた今からでもUnityを勉強しなおしております。
勉強と言えば、Unityの本を買って、チュートリアル通りにゲームを作成して・・・
みたいな感じにしようかと思ったのですが、それは昔一度通った身。
同じことを繰り返しても身につくことは少なそうなので、
今回は簡単なゲームを頑張って自分ひとりで調べながら作成する
ということを目標に勉強することにしました。
今回勉強のために作成するゲームはいわゆる「〇×ゲーム」。
〇と×を交互に置いていって、1列揃えたら勝利!というゲームですね。
単純なゲーム性であり、将来的にボードゲームやカードゲームなどを作ってみたいと思っているので、
それの足掛かりとしてもちょうどいい難易度でないかな?
Unityのインストールとセットアップ
さて、本来であればUnityとはなんぞや?という説明から、Unityのインストール、セットアップまでを解説すべきなのでしょうが、
今回は省略させていただきます
そもそもググればいろんな記事が死ぬほど出てくる情報ですし、
Youtubeなんかで調べたらそれこそ動画で至極丁寧に解説されてるものもありますしね。
Macであればこちらの動画がわかりやすかったです。
プロジェクトの作成
Unityをインストールしたらまずはプロジェクトの作成。
Unityは3Dゲーム、2Dゲームなどを作成できる開発ツールなのですが、今回作成するゲームは〇×ゲーム。
2Dで十分(というか3Dにする必要がそんなにない)ので、2Dのプロジェクトを作成します。
下図のように、[2D]を選択して、プロジェクト名に「maru batsu game」と入力。
できたら[プロジェクトを作成]をクリックします。
うまくいくと以下のような画面が出力されます。
ここまでは昔の記憶でなんとか行けましたね・・・
オブジェクトを配置してみる
さて、ここまではUnityやC#を触ったことのない人でも簡単にできるフェーズ。
ここからが勉強です。
まずは作りたいゲームのおさらいから。
〇×ゲームとは、3×3の盤面に、2人のプレイヤーが交互に〇と×を置いていくゲーム。
ということで、必要なモノは
- 3×3の盤面
- 「〇」マーク
- 「×」マーク
- 説明用のテキスト(今は〇の手番ですよ、みたいな説明)
- 一緒にやってくれる友達
です。
これらをUnityというゲームエンジンを駆使して作っていくことになりますね。
今回はPart1、ということで、『3×3の盤面』と『説明用テキスト』を作成してみたいと思います。
3×3の盤面を作ってみる
まずはゲームの根幹を担う、盤面の作成から。
いくら〇と×があっても、盤面がないとゲームとして成り立たないですからね。
というわけでさっくりとやってみましょう。
現在の状態は画面も真っ黒(というか灰色?)で何もない状態です。
盤面を作りたいので、四角い何かを配置したい。
とりあえず何か四角いものを置いてみましょう。
デフォルトだと、左側に[Hierarchy]と書かれた場所に、[SampleScene]と[Main Camera]というものが書かれていると思います。
今回は四角い何かをゲームに取り込みたいので、
[SampleScene]を右クリックして、
[Game Object] -> [2D Object] -> [Sprites] -> [Square]
をクリックします。
すると、下のように、画面に白い四角い何かが生成されました。
これがいわゆるGameObjectってやつですね。
ちなみに、このGameObjectというやつ、
実態がなくても作成することができます
実際に作成してみます。
まずは先ほどと同じように[SampleScene]を右クリックして、
[Game Object] -> [Create Empty]をクリックします。
すると、画面上には何も変化がありませんが、[Hierarchy]ウィンドウには新しいGameObjectが生成されました。
とりあえず名前を「Board」に変えておきます。
これは、画面には何も表示していませんし、現在のところあってもなくても見た目にも動作にも関係ないものですが、この「空のGameObject」には色々な使い道があります。
まずはその一例。先ほど作った四角いGameObjectと親子関係にしてみましょう。
先ほど作成した[Square]というオブジェクトをドラッグして、[Board]にドロップします。
すると・・・
こんな感じで、[Board]の下に[Square]が配置されました。
これをオブジェクトの親子関係って言います(というか勝手にそうよんでる)
関連のあるオブジェクトを整理するためにまとめたり、スクリプトからオブジェクトを探したりするときに役に立つテクニックなので、覚えておいて損はありません。
スクリプトって何ぞや?は後述
[Square]というオブジェクトの名前も「BoardPanel」にリネームしておきます。
あとは、[Board]オブジェクトの下に[BoardPanel]を9個作成しましょう。
コピペすると簡単に複製することができます。
9個作ったのに、画面上では1つしかないじゃん!と思った方。
これは、1番目にあるオブジェクトの後ろに残りのオブジェクトが重なっており、隠れてしまっているだけです。
一番上にあるオブジェクトをドラッグしたりして位置を調整すると、残りのオブジェクトも見えるはず。
というわけで、いい感じに整列させてみました。
なんかそれっぽい3×3の盤面が完成しましたね!
手番プレイヤーの表示テキストを作ってみる
とりあえず盤面はそれっぽく作成できました。
あとは〇や×を置けるようにするだけ・・・
と、ちょっと待ってください
このまま〇や×を置けるようにすると、今〇の番なのか、それとも×の番なのかが分からずに、
〇と×を間違えておいてしまったり、〇の人が連続しておいてしまったり等
ゲームの進行に混乱を招いてしまう可能性があります。
そうならないように「今は〇の番です」みたいな、手番がわかるように文字を出力するようにしましょう。
文字を表示させるには、TextMeshProというGameObjectを使います。
今までと同じように、右クリックして
[UI] -> [Text – TextMeshPro]をクリック。
すると、Hierarchyウィンドウに[Canvas]というオブジェクトと、[Text(TMP)]というオブジェクトが現れます。
なんか変な画面が出た場合
ちなみに、この動作によって以下のような画面が出た場合は、以下画像の赤枠の部分をクリックして必要なものをインポートしてください。
すると、下のAseetsウィンドウにTextMeshというフォルダが生成されます。
しかし、肝心のテキストが見当たらない。
そんな時にはHierarchyウィンドウの[Canvas]をダブルクリックしてみましょう。
すると、カメラがぐぐーっと引いていき、こんな感じでテキストが表示されていると思われます。
え、なんか今まで操作してた画面がめっちゃ小さいんだけど!!!
ってなった方が多いと思いますし、自分もその一人でした。
ですがご安心ください。
最終的になんかいい感じになります。
というわけで続き。
とりあえずテキストの表示はできていることが確認できたので、テキストの内容を変更してみます。
HierarchyウィンドウでTMPを選択すると、右側に[Inspector]というウィンドウが表示されると思います。
その中に、「New Text」と書かれている部分があると思うので、それを「@のターン」に書き直してみます。(下図赤文字)
すると
なんか文字化けしてる?
これは、Unityにインポートされているデフォルトのフォントが日本語に対応していないため。
なので、日本語文字は□と表示されてしまいます。
解決方法としては、日本語に対応するフォントを用意することですが・・・
ちょっと書くのが面倒なので各自調べてください
私は以下の記事を参考にしました。
というわけでフォントを用意して修正。
日本語対応フォントをTMPの[Font Asset]に設定すると、無事日本語を表示させることができましたね。
もし日本語フォントを用意するのが面倒だった場合は、英語で「maru turn」とか書いとけばいいと思います(適当)
あとはテキストの位置と大きさをいい感じに修正して(下図赤枠部分をいじればよい)
手番表示のテキストは完成!
一旦、「@のターン」という表示にしていますが、これは後でプログラムから変更します。
手番に対応して「〇のターン」「×のターン」という表示に変わるので安心してください。
ここまでできたら実際のゲーム画面を表示させてみます。
真ん中の画面の上に[Scene]と[Game]というタブボタンがあると思います。(下図赤矢印)
[Game]を押してみると、実際のゲーム画面ではどういう風に見えるか、を確認することができます。
先ほど、「テキストめっちゃ大きいじゃん!!」と言っていましたが、実際の画面ではいい感じの大きさになっているのがわかりますね。
これは、「UIの領域と普通のオブジェクト(という表現が適切か分からないが)の領域がそれぞれ異なるから」です。
よくわからない?自分もわからん
UIオブジェクトとそれ以外のオブジェクトはパラレルワールドに住んでいて、実際のGameではそれぞれの世界線が合わさって見える、みたいな感じに捉えておきましょう
ゲームシステムを作る準備をしよう
さて、盤面も作成できたし、UIの実装も簡易ながらできた。
ここからはようやく〇や×を盤面に置く、というゲームの根幹を作っていくフェーズです。
現状、盤面用のオブジェクトを配置してそれっぽく見せてはいますが、
マウスでクリックしてみても、ドラッグしてみても何も動作しない”でくの坊”です。
まずは「盤面をクリックしたら何かしら動作する」ようにしてみましょう。
当たり判定を設定する
とはいえ、今の状態だと、盤面をクリックしても何も起こりません。
というか、クリックという行為ができない状態となっています。
なぜなら当たり判定がないから
クリックしても当たり判定がないので、クリックされたことに気づくことができない状態です。
クリックだけではなく、当たり判定がないオブジェクトは攻撃することも、攻撃を受けることもできません。
なので、ゲームを制作するにおいて当たり判定というのはとりあえず与えておいても良いぐらいの重要な要素だったりします。
そんな大事な当たり判定ですが、Unityでは超簡単に付けることができます。
まずは当たり判定を付けたいオブジェクトを選択して、
右側の[Inspector]ウィンドウの[Add Component]をクリック。
検索欄に「Box Collider」と入力すると、「Box Collider 2D」というコンポーネントが出てきます。
それをクリックすると選択していたオブジェクトに当たり判定を付けることができます。
対象のオブジェクトのInspectorウィンドウの下に、Box Collider 2DがあればOKです。
※下図赤枠
同様に9個すべてのBoardPanelに当たり判定を付けておきましょう。
プログラミングをしてみる
盤面に当たり判定を付けたのはいいですが、今のままではクリックしても何も反応してくれません。
なので、クリックしたときのイベントを作ってみましょう。
手始めに、BoardPanelをクリックしたらクリックされたBoardPanelの名前を出力するようにしてみます。
そのためにはプログラミングをする必要があります。
Unityで使用するプログラミング言語はC#。
ある程度のプログラミングに対しての知識は必要ですので、まあそこは各自勉強ということで・・・
まずはプログラムを格納するフォルダを作成します。
下の[Asset]ウィンドウで右クリックして、
[Create] -> [Folder]をクリック。
新しく空のフォルダが作成されるので、名前を「Scripts」にしておきます。
ここにC#スクリプトを格納していきます。
Scriptsフォルダの中に移動したら、今度はC#Scriptを作成します。
フォルダを作成した時と同様に、
下の[Asset]ウィンドウで右クリックして、[Create] -> [C# Script]をクリック。
C# Scriptが作成されるので、名前を「GameManager」としておきます。
注意点として、生成したC# Scriptを一旦保存して後で名前を変更する、ということは基本しないでください。
クラス名とかその辺云々がめんどくさいことになってしまいますので・・・
C# Scriptが生成できたら、[GameManager]をダブルクリックしましょう。
すると、おそらくVisual Studioというツールが立ち上がって、以下のプログラムが表示されるはずです。
これから嫌というほど見ることになるスクリプトですね。
void Start()とかvoid Update()とか色々書いてますね。
それぞれの意味は各自調べてもらうとして、今回は以下のように書き換えてみましょう。
上から解説していくと
[SerializeField] GameObject clickedGameObject;
これはクリックされたオブジェクトを保存するための変数です。
なんでか[SerializeField]ってついてるけど、要らないです。
代わりにprivateとかつけておきましょう。マジでなんで付いてんだろ?
if (Input.GetMouseButtonDown(0)){
マウスが左クリックされたときの分岐です。
これによって、クリックされたらif配下の処理を実行するようになります。
clickedGameObject = null;
最終的にクリックされたGameObjectを格納するclickedGameObject変数ですが、
一応念のため初期化しておきます。
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit2D hit2d = Physics2d.Raycast((Vector2)ray.origin, (Vector2)ray.direction);
ここが今回のキモ。
どうやってオブジェクトがクリックされたかを判定する根幹部分です。
まず、Camera.main.ScreenPointToRay(Input.mousePosition)によって、マウスカーソルの場所に向かって光線を発射します。
そして、Physics2d.Raycast((Vector2)ray.origin, (Vector2)ray.direction)によって、その光線に当たった情報を取得しています。
イメージ図としてはこんな感じ。
if (hit2d)
{
clickedGameObject = hit2d.transform.gameObject;
}
この部分で実際にGameObjectを取得しています。
hit2dがどのオブジェクトにも引っかからなければ処理されないです。
Debug.Log(clickedGameObject);
コンソールに取得したGameObjectを出力します。
というわけでプログラミング完了です。
では早速ゲームを実行するとクリックしたらGameObjectが・・・
取れませぇん!
C# Scriptは作成して保存しただけではゲームに直接影響しません。
ではどうやったらゲームに取り込めるかというと、何かしらのGameObjectにアタッチする必要があります。
今回は[Board]にアタッチしてみます
まずは[Board]オブジェクトを選択して
先ほど作成した[GameManager.cs]を[Board]オブジェクトのInspectorウィンドウにドラッグ&ドロップします。
すると、コンポーネントとして先ほど作成したスクリプトが追加されます。
これでアタッチ完了です。
ではゲームを実行してみましょう。
真ん中上部にある「▶」ボタンを押すとこれまで作成したゲームを実行することができます。
というわけでプレイしてみます。
任意の盤面をクリックしてみると、Consoleにクリックされたオブジェクト名が出力されます。
こんな感じ。
ちなみに、Consoleを出力させるには、下の[Console]タブを押せばよいです。
Debugとかエラーを確認するのに必須のウィンドウなので、覚えておくとヨキ。
まとめ
というわけで、Unityで〇×ゲームを作るPart1でした。
今回は盤面と簡単なスクリプトの作成だけでしたが、次回からよりゲーム制作っぽくなっていくはずです。
とはいえ、かなりボリューミーなのでいつになるかわかりませんが・・・
また、この記事を見てUnityに興味を持った方はぜひこの本を買って読んでみてください。
この人の本は本当にわかりやすくて、C#があまりわからない人もなぞっていくだけである程度の理解がすることができます。
かく言う自分も最初はこの本(2019年verですが)でUnityを勉強しました。
今でも「これなんだっけ?」というときに参考にしたりする本です。
コメント