前回まででVRシューティングテトリスのロジック構築は終了です。
今回はゲームの味付けとしてスコア表示・テトリスブロックが一列揃った時に消えるエフェクトの追加を行いましょう。
前回の記事↓
スコアの表示と得点処理の作り方
今回は、一列揃ったらスコアが追加されるようにします。スコアはフィールドの隣に表示させるようにしていきます。
スコア表示用のテキストオブジェクトの作成
まずは、スコア用の3Dテキストを生成してください。ヒエラルキー上で右クリック→Create Object→3DTextから作成できます。
テキストオブジェクトでは、フォントの種類、文字の整列方法、色などを調整することができます。
今回生成したテキストオブジェクトのインスペクターは次のように設定しましょう。位置はフィールドの隣になるように適宜調整してください。
おおまかにフィールドの右上に配置出来ればOKです。
次に、生成したテキストオブジェクトをCrtl+Dで複製して、スコア用のテキストオブジェクトの他に、ラベル用のテキストオブジェクトも作成してください。スコア用のテキストオブジェクトはラベル用のテキストオブジェクトの下に配置されるように調整してください。あとは、ラベル用のテキストオブジェクトのテキストを「Score」に、スコア用のテキストオブジェクトには「00000」に変更しましょう。
それぞれのインスペクタが次のようになります。
名前等を調整後、下のようになっていればOKです。
スコアを計算する処理
では次に、スコア用テキストの表示が変えられるようにコードを編集していきましょう。
今回は、簡単に実装するためField.cs上でスコア用のテキストオブジェクトを編集できるようにします。以下を追加してください。
1 2 3 4 5 6 7 8 9 |
// スコア用のTextMesh [SerializeField] TextMesh scoreTextMesh; // スコアの値 int score; // ブロックを一列消去した際に追加するポイント const int DELETE_POINT = 120; |
このTextMeshというのはテキストオブジェクトでフォントなどを設定できる箇所のコンポーネントになります。これにより、テキストの中身を編集できるようになります。
今回は、変数scoreの値をscoreTextMesh.textに反映させることを考えていきます。今回はゲットできるポイントは120としました(自由に変更して大丈夫です)。ブロックが一列消えた時にスコアを増やしたいため、CheckLines()内の一列揃った場合の分岐内にスコアを追加する処理を追加していきます。以下のように変更してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
//消えているかどうかチェック void CheckLines() { for (int i = 0; i < 20;i++) { bool isDelete = true; for (int j = 0; j < 10;j++) { //上から順に調べたいため、「i」ではなく「20-i-1」を使用する if(!blocks[j,20-i-1]) { isDelete = false; break; } } //削除できる列 =「isDeleteがtrue」であれば削除 if(isDelete) { //一列ブロックを削除 DeleteBlocks(20-i-1); //消えた分だけブロックを下げる DropBlocks(20-i-1); //スコアを追加 score += DELETE_POINT; scoreTextMesh.text = "" + score; } } } |
最後に、Unityに戻ってFieldのインスペクターからScoreTextMeshにScoreTextをドラッグ&ドロップしましょう。これで準備完了です。
この状態で実行してみましょう。ポイントが追加される様子が確認できれば成功です。
【演出】テトリスブロックの消去エフェクトの作成
ゲームオブジェクトの作成
次に、ブロックが消えた時にエフェクトが表示されるようにします。
まずは、ヒエラルキーに空のゲームオブジェクトを作成してください。名前はDeleteEffectにしましょう。
次に、アニメーションを追加するため、Animatorコンポーネントを追加してください。
次に、Animatorフォルダを作成してください。
その後、AnimatorフォルダにDeleteEffectという名前のAnimation ControllerとAnimationを追加してください。
さらに、Animation ControllerをDeleteEffectのAnimatorコンポーネント→Controllerにドラッグ&ドロップしてください。これで、アニメーションを追加することができました。
そして、アニメーションを編集しやすくするため、DeleteEffectをPrefabsに入れておいてください。
アニメーションの編集
PrefabsフォルダのDeleteEffectをダブルクリックしてください。すると、DeleteEffectのみがフォーカスされた画面に切り替わります。この状態でアニメーションを編集していきます。
今回は、Cubeを4個使ってアニメーションを作ることにします。まずは、子オブジェクトとしてCubeを4つ作成してください。
次に、Window→Animation→Animatorを選択してAnimatorウインドウを表示させてください。
先ほど作成したAnimationをドラッグ&ドロップしてください。
右クリック→Create State→Emptyを選択してNew Stateアニメーションを作成してください。
次に、DeleteEffectを右クリック→MakeTransitionを選択してください。すると、矢印が伸ばせるようになります。
この矢印を先ほど作成したNew Stateアニメーションにつなげてください。
では、次にDeleteEffectアニメーションの中身を作成していきます。Window→Animation→Animationを選択してAnimationウインドウを表示させてください。
Animationウインドウを出せたら、録音ボタンを押してください。
タイムラインは20のメモリまで移動させてください。
この状態で、Cubeを移動させていきます。すると、4つのCubeがAnimationウインドウに登録されます。
RotationやScaleも変更できます。ここでは、最後に見えなくするため、Cubeのスケールをすべて(0,0,0)に設定させてください。
この状態でタイムラインを操作すると、時間とともにCubeの位置やサイズが変化していく様子が確認できます(ここで、お好みのアニメーションに設定してみてください)。
アニメーションをスクリプトから操作するための準備
アニメーションを作成したら、スクリプトから操作できるように編集していきましょう。
AnimationコントローラのNew Stateを選択してください。
そして、インスペクタ―からアニメーション名をFinalSceneに変更しておいてください。
これにより、DeleteEffectアニメーションが終了した後に、FinalSceneへ遷移することが分かるようになります。
アニメーションをスクリプトから操作する
では、アニメーションを操作するためのスクリプトを作成していきましょう。新しいスクリプトとしてProjectウインドウ上でDeleteEffect.csを作成してください。
忘れないうちに、PrefabsのDeleteEffectにDeleteEffect.csを追加しておきましょう。
では、コードの説明に入ります。下記のコードを作成してください。
このコードは、animatorのアニメーションがFinalSceneになったタイミングで、自分自身を消去するコードになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class DeleteEffect : MonoBehaviour { Animator animator; // Start is called before the first frame update void Start() { animator = GetComponent<Animator>(); } // Update is called once per frame void Update() { var a = animator.GetCurrentAnimatorStateInfo(0); if(a.IsName("FinalScene")) { Destroy(this.gameObject); } } } |
そして、これを好きな場所で表示できるようにするため、Field.csから参照できるようにしましょう。以下を追加してください。DeleteBlocks()により消去されるブロックがわかります。そのため、そのブロックの位置でDeleteEffectが生成されるようにします。(今回は簡易的に見やすくするため、Vector3.back*0.1fを加えてユーザ手前でアニメーションが見えるようになっています)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
[SerializeField] GameObject deleteEffect; // 省略 void DeleteBlocks(int h) { //一列ブロックのGameObjectを削除する GameObject[] glist = GameObject.FindGameObjectsWithTag("block"); foreach(GameObject go in glist) { if(go.GetComponent<Block>().y == h) { GameObject deleteEffectClone = Instantiate(deleteEffect); deleteEffectClone.transform.position = go.transform.position + Vector3.back*0.1f; deleteEffectClone.transform.localScale = Vector3.one * 0.1f; blocks[go.GetComponent<Block>().x, h] = false; Destroy(go); } } } |
ここまで記述したら、Fieldのインスペクタ―からDeleteEffectを割り当てましょう。
これで準備完了です。
実行すると、以下のような結果になります。
お疲れ様でした。
ここまででVRシューティングテトリスの講座は終了です。
演出面や対戦機能など面白い機能を追加していってください^^
コメント
作成後のField.csのScriptファイルの中身を見たいのですが可能でしょうか?
コメントありがとうございます。お返事遅くなりました。
このファイルもう今手元にないんですよね・・・すみません。
かなり初期の頃に作った講座なので一部不具合があるかもしれません(講座のまとめページで不具合ある旨記載済みですが確認できてなかったらすみません)。
VR系の実装について学びたい場合、FPS講座やレーシングゲーム講座を使っていただければ幸いです。
こちらは完成時プロジェクトファイルごと保存してダウンロードできるようにしてあるので(ただし有料になってます)。
お手数おかけしますがよろしくお願いいたします。