たくあんポリポリ

勉強したことを載せていきます。最近、技術系の記事はZennに書いています。(https://zenn.dev/chittai)

VRでゲームを作って遊んでみた~飛んでくる弾を切る~

休日を使い、一気にゲームを作りきってみました。ステージ作成、クリア・ゲームオーバー判定などなど、、、まだまだ甘いところは多いけど、ひと段落ついたかなといった感じです。その勢いのまま、多田くんは恋をしないを見始めました。荒ぶった心に染み渡る。

tadakoi.tv

やったこと

やったこと一覧を書き出すと↓になります。

  • ステージを作成する
  • クリア判定できるようにする
  • ゲームオーバー判定できるようにする
  • タイトル画面を作成する
  • ボタンを押したらゲームスタート/リトライ
  • 改善:剣を常に持った状態にする
  • 改善:HPのUIを変える

ステージを作成する

今回は、 Terrain を使用してステージを作成しました。それと、アセットで無料のSkyboxを使用しました。

Terrain

Hierarcy -> 3D Object -> Terrain で使用します。今回は、下の画像の赤枠で囲まれた機能を使いました。
f:id:c_taquna:20180528222636j:plain

左の赤枠でTerrainに凹凸をつけ、ある程度自分を囲むようにしました。そうすることで、自分がいるスペースがただ広がっているのではなく、障害物に囲まれた制限のある空間であると認識させたかったからです。そうすることでゲームの臨場感がますなと思い。右側の赤枠で木のオブジェクトを配置しました。使用したアセットは↓

assetstore.unity.com

Skybox

Skyboxは Window -> Lighting -> Settings -> Skybox Material で使用したいSkyboxを指定します。
assetstore.unity.com

こんな感じになりました。
f:id:c_taquna:20180529022237j:plain

クリア判定できるようにする

クリア判定をするためには、クリアの条件を決める必要がありますが、今回は10秒間死なないとクリアになることにしました。もっといい条件があったのかもしれないですが、弾に当たらないようにするゲームなので、時間制限で問題ないかなと思いました。

つまり、ゲームがスタートしてから

  1. 10秒計測し、
  2. 10秒立ってもHPが0になっていなければ、
  3. ゲームクリア。

という処理にします。

今回、ゲームが終わる条件として、GameEndFlag というフラグを作成しています。これは、ゲームがクリアした場合とゲームオーバーになった場合に1を入れます。下記スクリプトだとGameEndFlag が 0(死んでいない)かつ、timer が10以上でクリアの処理に入ります。

void Update () {
        timer += Time.deltaTime;
     <略>
        if (GameEndFlag == 0 && timer >= 10) {
            Destroy(BulletGenerator);
            CongratulationsText.enabled = true;

            GameEndFlag = 1;
        }

スクリプトの中では、クリアしたら弾の生成を中止し、クリア用の「Congraturations!!」という文字を空中に表示します。あとでゲームオーバの処理も書きますが、クリアとゲームオーバーの違いは演出の違いによって違いをだしています。
f:id:c_taquna:20180529022529j:plain

ゲームオーバー判定できるようにする

ゲームオーバーもクリアと似たような感じです

  1. 時間が10秒たっていない状態で、
  2. HPが0になったら、
  3. ゲームオーバー

となります。

        if (GameEndFlag == 0 && UserHP <= 0) {
            Destroy(BulletGenerator);
            GameOverText.enabled = true;
            GameOverPanel.SetActive(true);

            GameEndFlag = 1;
        }

ここではもゲームオーバーになった時点で弾の生成を中止し、「You Are Dead」という文字を空中に表示しています。ゲームオーバーの時は演出として、赤くて透明なPanelを表示して、いかにも死んでしまったかのように見せています。このあたりもソードアートオンラインを参考にしました。
f:id:c_taquna:20180529022615j:plain

タイトル画面を作成する

再生したらいきなり弾が飛んでくるのではなく、タイトル画面(今回だとメニュー画面という言い方のほうが正しい気がする)を一番最初に表示して、何かしらのアクションをトリガーにゲームが始まるようにしました。

  1. タイトル画面用のシーンを作成して、
  2. ボタンを押すと、ゲームシーンを読み込むようにする
タイトル画面用のシーンを作成する

ゲームのプレイシーンと同じ配置にしたいので、ゲームのプレイシーンで File -> Save Scene as... から別の名前で保存します。必要な情報だけ残して、ほとんどのオブジェクトを Hierarcy から削除します。

そうしたあとに、以下のスクリプトを書いて空のオブジェクトにアタッチします。そうすると、Fire1=Oculus TouchのAボタンを押すとゲームのプレイシーンがロードされゲームが始まります。これは、ゲームオーバ時やゲームクリア時にも同じ処理を書いているので繰り返しゲームをプレイすることが可能になっています。

void Update () {
        if (Input.GetButtonDown("Fire1"))
        {
            SceneManager.LoadScene("Sword1/Sword1"); ★ゲームのプレイシーンは "Sword1"
        }
}

それに加え、Aボタンを押すことを促すために空中に「PUSH "A" TO START」を表示しています。今までのゲームでもそうですが、ゆっくりと点滅すると自然とそこに視線がいくので今回はその処理も追加しています。

        blinkText.color = new Color(1,1,1,Mathf.PingPong(Time.time,1));

この処理を入れることで、ゆっくりと文字が点滅します。blinkTextというのが今回空中に表示している文字です。

改善:剣を常に持った状態にする

今回、HecomiさんのGrabberを使っていましたが、それをやめて剣を直接手の動きに合わせて動くようにしました。正直、手が見えてものがつかめるよりも、こっちの方がプレゼンスが非常に高いように感じました。空間に何もなくても、手の動くに合わせて剣が動くことで、頭の中で補完されるのか剣がある位置に自分の手の手がある様に感じることができました。

OVRCameraRig -> TrackingSpace -> RightHandAnchor に剣を配置することで、手の動きに合わせて剣を動かせます。それと、ポイントとしては剣先が相手に向く方法に60度ほど倒して上げるとすごく剣を使いやすくなります。

改善:HPのUIを変える

HPのUIを変えました。よりソードアートオンラインのGGOに近いかたちにしようかなとおもい黒背景に白ゲージにしました。HPが一定量下がることで、HPゲージの色が白→黄色→赤と変化するようにしました。
f:id:c_taquna:20180529022814j:plain
f:id:c_taquna:20180529022917j:plain
f:id:c_taquna:20180529022923j:plain

感想

自分のメモに近い記事ですが、一旦ゲーム機能作成が完了したので、これをブラッシュアップするか別のことするかを考えようかなと思います。