Unityの学習方法はたくさんあります。公式のチュートリアルや書籍、ブログ、YouTubeやUdemyなどの動画教材、有料のオンラインスクールなどがあります。
今回は『i-school』というオススメのサイトを紹介させてもらいます。
i-school
https://i-school.memo.wiki
i-schoolはUnityのゲーム制作を学ぶためのサイトで、無料で利用できます。豊富な教材があり、どれを始めればいいか迷うこともあるかもしれません。
Unity初心者の悩み:
ゲーム開発を始めたいけれど、どの教材を選べばいいのか、どうやって始めればいいのかわからない。特に、初心者向けのわかりやすい教材が欲しい。
今回はその中から1つ、『2Dパズルゲーム』を学習しましたので、その内容を共有したいと思います。
目次
i-schoolの『2Dパズルゲーム』について
ゲーム内容
同じ絵柄の干支をドラッグ(スワイプ)して消していくパズルゲームです。
干支を消したら消した数だけ上からランダムに干支が降ってきます。
消した数だけ得点が入り、制限時間内にハイスコアを目指すといったゲームです。
学習の振り返り
それでは、実際に作ってみて学んだ内容を振り返りたいと思います。
基礎編は手順15まであります。
各手順を振り返る
手順のタイトルがリンクになっていますので、各ページへ飛ぶことができます。
手順1~2 <パズルゲームのベース部分を作成>
プロジェクトの作成
Canvasの設置と設定
背景用のオブジェクトを配置し、背景画像を設定をします。
(とりあえず教材と同じフリー素材を探して使用することにしました)
干支のブロックが落ちないようにするために、見えない壁を作ります。
左右の壁はBoxCollider2Dで設定。
下の見えない壁は少し複雑で、画像に合わせてEdgeCollider2Dで設定します。
7か所ポイントを作り、それぞれの座標を設定しました。
こういうのはキリがいい数字にしたくなる
GameData.csの作成
GameDataはインスタンスで作成します。
何種類の干支を生成するか制限するためのEtoTypeCount変数、ゲーム開始時に生成する干支の数を設定するCreateEtoCount変数を用意します。
フリー素材から干支のイメージを用意します。
SpriteEditorで12分割します。
Prefab用のオブジェクトを作成します。
分割した画像を設定し、落下させるためのRigitBody2Dと、当たり判定を行うためのCircleCollider2Dを追加します。
設定が終わったらPrefab化します。
手順3~7 <干支が消えるロジックを組み立てる>
EtoSetTranというオブジェクト作成し、干支の生成位置にします。
GameManager.csを作成し干支の角度と落下位置をランダムになるようにします。
12種類の干支の名前を登録するためのEtoType.cs作り、enum(列挙型)にします。(MonoBehaviourクラスを継承しないenumのみになります)
enumのみのスクリプトの場合、クラスの継承とusing宣言は不要。ゲームオブジェクトにアタッチも不要で、他のスクリプトからでも参照できる。という感じらしい。
enum難しい!
たくさん教材やって覚えていくしかないなぁ
EtoPrefabの画像を変更するためのEto.csを作成します。
EtoPrefabにアタッチし、生成されたタイミングでランダムに選ばれた干支の種類に合わせて、画像と名前が変わるようになります。
12分割した画像を一つ一つ名前を変えます。
eto_0~etp_11にします。
Resourcesフォルダを作り、その中に画像を入れる。
メモ:フォルダには一部特別な意味を持つフォルダがあり、Resources内に置かれたファイルはスクリプトを通じてゲーム内でファイルを取得することができる。
GameManager.csを修正し、画像を読み込んで干支をランダムに生成するようにします。
またコルーチンメソッドを使用しているため、画像の読み込みと配列の代入が終わってから干支を生成するような流れになっています。処理の流れをきちんと作ってあげることで不具合の発生を防げる設計になっています。
コルーチンは処理の流れを正しく制御したいときに使う!
GameManager.csを修正し、最初の干支をタップした時の処理を追加します。
ゲーム画面をタップした時、Cameraを使い座標を算出し、その位置にコライダーを持つオブジェクトがあった場合、Etoクラスを持っているか確認。変数の代入や情報の取得や、削除対象としてListに追加などを行います。
タップした干支のアルファ値を0.5にし半透明にします。
タップした干支が半透明になりました。
(この段階ではまだドラッグ(スワイプ)での連鎖や干支を消すことはできません)
同じ干支同士をドラッグ(スワイプ)して繋げられるようにします。
GameManager.csに、ドラッグした先の干支の判定を行うメソッドを追加します。
最初にタップした干支と同じ絵柄かつ、最後にタップしている干支と現在の干支が違うオブジェクトであり、現在の干支がすでに「選択中」でなければ処理を行います。
Vecter2.Distanceメソッドを使用して距離を比べます。
最後にタップしている干支との距離が、一定の距離以内なら繋がるようになります。
連鎖数のカウントや、削除対象のListに追加などを行います。
ドラッグをやめた時(指を離した時)、干支が3つ以上繋がっていたら消えるようにします。
消えた干支の数だけ新しく干支をランダムに生成させます。
2つ以下の場合は干支は消えずに選択中の状態を解除します。
手順8~10 <UIを追加する>
画面上部と下部にUIを作っていきます。
Scoreという文字の部分、スコアの数字の部分を共通のPrefabにして作ります。
どこまで共通のPrefabを使用するのか、自分の作るゲームプロジェクトに合わせて上手な利用方法を考える必要があると思いました。
GameData.csを修正します。
スコアと消した干支の数をカウントする変数を用意し、ゲーム開始時にスコアを初期化するメソッドを追加します。
UIManager.csを作成します。
スコアを更新するメソッドを作成します。
GameManager.csを修正します。
AddScoresメソッドで干支を消したときのスコアの加算の処理をし、スコアの表示を更新するためにGameManagerに宣言フィールドを追加し、UIManagerと紐づけをします。
紐づけをすることでGameManagerからUIManagerのメソッドを実行することができます。
残り時間のUIを作成します。
絵馬の画像を使用し、数字の部分はスコアと同じPrefabを使用します。
GameData.csを修正し、残り時間と現在の時間の変数を用意します。
UIManager.csを修正し、GameManagerから引数を受け取り画面上の残り時間の表示を更新します。
GameManager.csを修正し、残り時間が0になるまで現在の時間を減らしていく処理を追加します。
Time.deltaTimeを使用することによって正確に時間を減らすことができます。
手順11~15 <ベースのゲームサイクルを作る>
GameManager.csにenum(列挙型)のGameStateを作成します。
GameStateにはSelect,Ready,Play,Resultの列挙子を用意します。
GameStateの状態によってゲームの状態を制御します。
Playになったら干支をドラッグで操作できるようになり、残り時間も減り始めます。
残り時間が0になったらResultになり、リザルト画面に移行するようにできます。
GameManager.csにGameStateの状態を変更する処理を追加します。
StartメソッドでGameStateをReadyにし、準備中の状態にします。
干支の生成が終わったらPlay状態にし、パズルの操作が可能になり残り時間が減り始めます。またUpdateメソッドはPlay状態以外では実行されないようにします。
残り時間が0になったらGameUpメソッドを実行し、Result状態にします。
スコアや消した干支の数を表示させるリザルト画面を作成します。
ゲーム画面の上の位置にResultPopUpというゲームオブジェクトを作成し、その中にPrefabを使用してTextの項目を追加していきます。
Buttonオブジェクトを作成し画面全体を覆い、画面をタップしたら後ほど追加するゲームを再スタートする処理が実行できるようにします。
DOTWeenを使用し、リザルト画面が上から降りてくるアニメーションを行います。
DOMoveYメソッドを使用し、ResultPopUpゲームオブジェクトを移動させます。
DOMoveY(0, 1.0f)
1秒かけてY軸を0の位置まで移動させるといった処理。
ResuluPopUp.csを作成します。
開始時にリザルト画面のボタン要素のをアルファ値を0にして透明にします。
DOtweenのsequenceを使い、スコア、消した干支の数の順番に表示させ、最後にボタン要素を表示させます。
ゲームを再スタートした際にリザルト画面が元の位置に戻るようにします。
ResultPopUp.csを修正します。
ゲーム開始時のResultPopUpのY軸の位置を変数に代入します。
リザルト画面を元の位置に戻し、ゲームを再スタートさせるOnClickMovePopUpメソッドを作成します。
btnClosePopUp.onClick.AddListener(OnClickMovePopUp);
スクリプトからボタンを押したときに実行するメソッドを登録することができます。
これによってButtonのInspectorの登録作業をする必要がなくなります。
GameData.csにゲームシーンを再読み込みするメソッドを作成します。
これによりリザルト画面をタップしたらゲームシーンが再読み込みされ、またはじめからプレイできます。
基礎編はここまでになります。
まとめ
この教材は、完成したゲームだけでなく、プログラムの組み方や新しいメソッドや要素について学ぶのにとてもおすすめです。操作手順が丁寧に説明されており、初心者でも最後まで取り組むことができる内容だと思います。
前回の2Dタップシューティングを学習済みなのと、ゲームの作りがシンプルになっているため、学習時間はそれほどかかりませんでした。
シンプルですが『State』といった重要な要素もあり、上手くゲームの状態を制御しないと、ゲーム開始前に操作できてしまったり、残り時間が無くなっているのにまだ動かせたりといったことになってしまいます。
ゲームの設計はしっかりやらないといけない。そして作っていく手順も大事なのだと思いました。
i-schoolの教材はオススメ!
i-schoolはとてもいいサイトです。
今回の教材に限らず、いい教材がたくさんあります。
是非Unityの学習に役立ててみてください。
この記事を読んで挑戦したり、実際に取り組んだ方々のコメントをお待ちしています。
基礎編を終え、次は発展編をやろうと思います。