たくあんポリポリ

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

VRシューティングゲームを作った(3作品目)

今回、Unityで3つ目のVRゲームを作ってみました。今まで勉強してきたものに、自分にとって新しい要素をいくつか取り入れました。
Menu画面のレーザーポインタもそうですし、直接は見えないですが今回はOculusRiftだけではなくOculusGoでビルドして遊べることも確認済みです。

今回作成したゲーム

youtu.be

使用した環境は以下

  • Unity 2018.1.3f1

今回やってみたこと

メニュー画面

今回はMenu画面からゲームシーンへの遷移を、UIのButtonをレーザーポインタで選択してトリガーを引くことで遷移できるようにしました。レーザーポインタの使用方法は以下の記事に書きました。

c-taquna.hatenablog.com

こういう表現を使うだけで、VRのUIっぽくなったなと。前回はコントローラのボタンを押すだけで遷移していたので。

UIについて

UIを使用していますが、見た目がおしゃれにするのは難しい。

メニュー画面のUI

たとえば、以下はMenuに配置したUIですが、これはPanelとButtonとTextを使用しています。PanelのSourceImageにゲーム画面のキャプチャを指定することで背景をゲームのプレイ画面にしています。そうすることで、プレイ画面に移ったあとの状態のイメージがしやすくていいなじゃないかなと。わからないものを選択するのは少しストレスがかかるし、今後拡張していく上でも自分が何を選択しているか視覚的にわかるようにしたほうが親切かなと思いこうしました。
f:id:c_taquna:20180709084439j:plain

リザルト画面のUI

UnityのSceneタブから撮ってきたキャプチャですが、この「New Text」の部分をスクリプトで変更して表示しています。例えば、TimeUPになったらResultには「Failed...」と表示させたり、Rankには残りのプレー時間がプレイ時間全体の何割かによってA~Cまでで評価しています。単純に条件分岐で判定しているだけですが、こういう自分のプレイが結果にフィードバックされる要素が増えるとよりゲームっぽくなるなーと思いました。
f:id:c_taquna:20180709085313j:plain

インスタンス変数で定義したm_Rankがあり、

public class PlayManager : MonoBehaviour {
    public Text m_Rank;

_PlayTime は現在の残りプレイ時間で_PlayTimeMax がプレイ時間の全体。なので、_PlayTime が_PlayTimeMax に対してどの程度残っているかによってm_RankのTextをA~Cに変更しています。

PlayTime = Mathf.Clamp(_PlayTime, 0, 30);
m_TimeText.text = "TIME : " + string.Format("{0:000}",_PlayTime);
_PlayTime -= Time.deltaTime;

if (_PlayTime >= (_PlayTimeMax * 6 / 10))
{
       m_Rank.text = "A";
}
else if (_PlayTime >= (_PlayTimeMax * 4 / 10))
{
         m_Rank.text = "B";
}
else
{
          m_Rank.text = "C";
}

ゲームのプレイ状態の判定

このへんはメモとして残しておきたいのですが、ゲームを作成している時に、Play状態とそうでない状態を明確に分けておいたほうが処理を書きやすいと思いました。

やり方としては、以下の様にゲームのプレイ状態を決める定数を定義します。

int_Playstatus; //ゲームのプレイ状態を入れるための変数
const int PLAY_START = 0;
const int PLAY = 1;
const int PLAY_END = 2;

あとは、switchを使いながら、各状態での判定処理を書いていきます。特に、ゲームクリアの条件などはプレイ中の処理にかいて、ResultUIの表示などを終了時の処理に書いています。

switch (_Playstatus)
{
    case PLAY_START:
	//ゲーム開始時の処理
        break;

    case PLAY:
	//ゲームプレイ中の処理
	if(<クリア条件>)
	{
        //GameClear時の処理
 		(略)
        }

        //TimeUp時の処理
        if (<TimeUP条件>)
        {
		(略)
        }
        break;

    case PLAY_END:
        
        //ゲームクリア・タイムアップにかかわらず、終了する際の処理

        break;

    default:
        break;
}

Oculus Go

今回はOculusGoでもビルドしました。360°的が存在して自分自身も回転するので、ゲーブルやセンサーがないOculusGoのほうが相性がいいです。というか、OculusGoで使用することを目指して設計したのでそうなるのは当たり前ではあるのですが。

感想

次は、新しい機能を追加したり、VTuber的な何かを作ってみようかな。アイデアはまだないですが。