CrossRoad

XRを中心とした技術ブログ。 Check also "English" category.

【Unity】GameJamで得たカウントダウン、効果音設定方法

これで最後です。OculusGameJamで作ったゲームの主な作り方を説明します。

ゲームの流れはこんな感じです。
(1)oculusRiftでPSeye越しに現実風景を見る(AR)
(2)マーカを認識して現実風景をふわっと削除(AR->VR)
(3)フォロワーアイコンを頭上に掲げたクマさん登場(VR)
(4)逃げてくクマさんを追いかけてフォロワーを再び!

今回は(4)を説明します。

1. 完成したゲームのイメージ

このゲームのルールはとても単純で、Twitterアイコンをかかげたクマが逃げていくので、時間内に捕まえるだけです。クマが逃げてく、というのはUnity仮面さんのこちらの記事を参考にしています。Unity仮面さん、ありがとうございます。

gihyo.jp

必要なAssetの入手や設定方法は記事の通りなので省略します。

記事と変えたところは下記です。

[1]カウントダウンタイマーを付けた
[2]クマにタッチすると、クマが消えるようにした
[3]クマにタッチすると、8bitの効果音が鳴るようにした
[4]クマにタッチすると、「あとXクマ」の表示が変わるようにした

ということで、最後はこの[1]~[4]を説明します。

1. カウントダウンタイマーをつける

1.1 3DTextオブジェクトの設定

まず、3DTextオブジェクトをGameViewに生成し、OVRPlayerControllerの視点から見える位置に配置します。名前はRemainedTimeとでもします。

次に、これをOVRPlayerController/OVRCameraController/RightCameraにアタッチします。

1.2 カウントダウン処理を行うスクリプトを作成する

CountDownTime.csを作成し、以下のように記述します。

using UnityEngine;
using System.Collections;

public class CountDownTime : MonoBehaviour {
	private TextMesh timeTextMesh;
	private float playTime = 150.0f;
	private string timeString;

	public bool timeOnFlag = false;
	void Start () {
		timeTextMesh = (TextMesh)this.gameObject.GetComponent<TextMesh>();
	}
	
	void Update () {
	  if(timeOnFlag == true){
		playTime -= Time.deltaTime;
		if(playTime > 0.0f){
			timeString = string.Format("{0:00}:{1:00}:{2:00}",  Mathf.Floor(playTime / 60f), Mathf.Floor(playTime % 60f), playTime % 1 * 100);
			timeTextMesh.text = "time\n" + timeString;
		}
		if(playTime <= 0.0f){
		//	Application.LoadLevel ("GameOver");
		}
			
	  }	
	}
}

timeOnFlagは、(2)でマーカ認識して1秒以上経つとtrueになります。つまり、AR->VRへ移行したときにカウントダウンが開始します。

次にplayTime変数を

playTime -= Time.deltaTime;

でデクリメントし、そのたびに、

timeString = string.Format("{0:00}:{1:00}:{2:00}",  Mathf.Floor(playTime / 60f), Mathf.Floor(playTime % 60f), playTime % 1 * 100);

で、表示内容を整形しています。数値を右寄せにするなどの処理はstring.Formatメソッドが便利です。


さらに、これを

timeTextMesh.text = "time\n" + timeString;

で3DTextに表示させています。

これをUpdate()の中で繰り返し実行されることで、Playerの目の前ではカウントダウンが確認できます。シンプルなので、経過時間に関するゲームでいろいろ使えて便利だと思っています。

2. クマにタッチすると、クマが消える処理を作る

実はこれがけっこう悩みました。普通タッチすると何かを起こすにはOnCollisionEnterとか、OnTriggerEnterを使えばよいのですが、

・Playerが近づくとクマが逃げる設定のために、OnTriggerStayを使っている。
->OnTriggerEnterがうまく働かなかった。
(やり方次第で何とかなったのかもしれないが、当日はそれ以上調べる時間がなかった)

・OVRPlayerControllerはCharacter Controllerなので、OnCollisionEnterが使えない

という問題があったためです。

結局はOnControllerColliderHitをOVRPlayerController.csに追加してなんとかなったのですが、最初はうまく動かずちょっと焦りました。

(このとき終了1時間前を切っていたため)

OVRPlayerController.csの末尾に追加した内容は以下です。

RemainedBear remaindBear;
SoundEffectTest soundEffectTest;

void OnControllerColliderHit(ControllerColliderHit hit){
   if(hit.gameObject.name == "RunningBear"){
   soundEffectTest.SendMessage("PlayAudioGetBear");
   remaindBear.SendMessage("GetBear");	
   Destroy(hit.gameObject);
   }	
}

クマオブジェクトはRunningBearとしています。今回はクマゲット時に効果音もつけたかったので、sound系の処理も入れています。

3. クマにタッチすると、8bitの効果音が鳴る処理を作る

実はサウンド関係も初めてでした。なのでざっと調べて最低限音が出るような仕掛けだけを入れました。

//SoundeEffectTest.cs
using UnityEngine;
using System.Collections;

public class SoundEffectTest : MonoBehaviour {
	
 public AudioClip audioClip1;

public void PlayAudioGetBear(){
 audio.PlayOneShot(audioClip1);
}	
	
	
}

書いたのはこれだけです。Hierarchy Viewに空のオブジェクトSoundTestを作り、そこに、Audio Sourceコンポーネントを付けてから、SoundeEffectTest.csをアタッチしました。AudioClipのaudioClip1には、それぞれwavファイルをアタッチしました。

にわか勉強ですが、Unityで音を扱うときは、

・音を出すオブジェクト:AudioSourceコンポーネントをアタッチ
・音楽データ:AudioClip
・音を聞くオブジェクト:AudioListenerコンポーネントをアタッチ

という決まりがあります。

今回はクマゲットのたびに効果音をPlayerの間近で発生させたかったので、SoundTestオブジェクトをOVRPlayerControllerの子にしてPlayerの移動と同期させました。

※最初はSoundTestオブジェクトを適当な位置に置いてたのですが、そうすると、SoundTestオブジェクトから離れたところでクマゲットしても効果音が小さかったです。


また、効果音には、AssetStoreの「8-bit Sounds Free Pacakge」のPickUp3を使いました。

4. クマにタッチすると、「あとXクマ」の表示が変わる処理を作る

これもカウントダウンのときと同じように3DTextをOVRPlayerController/OVRCameraController/RightCameraの子にしてから、以下のスクリプトをアタッチしただけです。

//RemainedBear.cs
using UnityEngine;
using System.Collections;

public class RemainedBear : MonoBehaviour {
	
  private TextMesh scoreTextMesh;
	
  SoundEffectTest soundEffectTest;
	
  public static int totalBear = 10;
  public static int getBear = 0;
  public bool scoreOnFlag =false;
  void Start () {
     scoreTextMesh = (TextMesh)this.gameObject.GetComponent<TextMesh>();
     soundEffectTest = GameObject.Find ("SoundTest").GetComponent<SoundEffectTest>();
  }
	
   void Update () {
    if(scoreOnFlag == true){
	scoreTextMesh.text = "あと\n" +(totalBear-getBear).ToString()+ "クマ\n";
	   if(getScore ==10){
		//Application.LoadLevel ("GameOver");
	    }		
    }	
   }	
    public void GetBear(){
	getBear = getBear + 1;
    }	
}

この中のGetBear()は、OVRPlayerController.csで呼んだ

remaindBear.SendMessage("GetBear");

のことです。

5.動作確認

こんな感じになります。

(再生時間4秒ですが、音が一回だけ出るのでご了承ください)

6. 終わりに

ゲームの主な特徴についてはこんな感じです。ところでGameJam終了後またPSMoveを使ったゲーム開発を再開しています。

次回のOcufes開催日程は未定ですが、もし近いうちにあるならばなんとか間に合わせたいと思っています。


参考までに、今回の関連記事です。

OculusRiftでPSeye越しに現実風景を見る方法 - CrossRoad

Oculus RiftでPSEye越しに現実風景を見て、VRに切り替える方法 - CrossRoad

【Unity】Twitter API 1.1を使って、フォロワーアイコンをVR空間に表示させる方法 - CrossRoad