Unityで2Dアクションゲームを作ろう⑤ ~障害物の自動生成~


Unityで2Dアクションゲームを作ろう⑤

Unityを使用した2Dアクションを作成する際に使用した方法やロジックなどを紹介していきます。

※注意 Unity4の頃に作ったものなので、いろいろと古いです。

障害物の自動生成


前回は以下の内容で進めてきました。
Unityで2Dアクションゲームを作ろう④ ~スタート画面とフラグ管理~

今回は、画面内に配置していた障害物(Wallオブジェクト)を自動生成する仕組みを実装します。

プレイヤーが障害物を突破した数を競うゲームでは、ゴールがなく、ゲームオーバーするまで続く仕様が一般的であるため、
障害物の数を予め決めることができません。
そういった場合、障害物は画面外などで自動生成し、画面から見えなくなったら自動削除するといった方法をとります。

さらに、前回まではPlayerオブジェクトをスクロールさせていましたが、自動生成ロジックの実装後は、障害物であるWallオブジェクト
を移動させることで、Playerオブジェクトもそれに追従するカメラも初期位置から動かさなくてよくなります。

今回行う自動生成は、正確には『自動でプレハブをインスタンス化』です。
スクリプトを作成し、インスペクターからプレハブを登録すると、その登録したプレハブが自動でシーン内に配置されるようになります。

プレハブを自動でインスタンス化するスクリプト


SpawnPoint.cs

using UnityEngine;
using System.Collections;

public class SpawnPoint : MonoBehaviour {

	public GameObject spawnObject;
	public float interval;

	void Update () {
		transform.position = new Vector3(transform.position.x, Random.Range(5f,30f), transform.position.z);
	}

	public void StartSpawn(){
		StartCoroutine("SpawnWalls");
	}

	public void StopSpawn(){
		StopCoroutine("SpawnWalls");
	}

	IEnumerator SpawnWalls(){
		while(true){
			Instantiate(spawnObject, transform.position, transform.rotation);
			yield return new WaitForSeconds(interval);
		}
	}
}

23行目のInstantiate()の中にあるGameObject型の変数spawnObjectに代入されたオブジェクトが自動で生成されます。
24行目のWaitForSeconds()のFloat型の変数intervalの間隔で、オブジェクトが生成されます。

StartSpawn()とStopSpawn()は、自動生成の開始と停止をするメソッドです。
GameControllerスクリプトなどからSendMessage(“StartSpawn”)といった形で呼び出してあげます。

10行目のVector3のY成分で使用しているのはランダム関数です。
Range(a,b)で指定したaとbの間の値をランダムで返します。

Wallオブジェクトを自動でスクロールと自動消滅させるスクリプト


自動でシーン内にインスタンス化するだけでは、同じ場所に何個もWallオブジェクトが生成させてしまいます。
生成したWallオブジェクトを自動で移動させて、画面外に出たら自動消滅するスクリプトを作成しましょう。

Wall.cs

using UnityEngine;
using System.Collections;

public class Floor : MonoBehaviour {

	public float scroll = 0.15f;
	Renderer cRenderer;

	void Awake(){
		cRenderer = GetComponent<Renderer>();
	}

	void Update (){
		float x = Mathf.Repeat(Time.time * scroll, 1);
		Vector2 offset = new Vector2 (x, 0);
		cRenderer.sharedMaterial.SetTextureOffset ("_MainTex", offset);
	}

	public void Stop (){
		Destroy(this);
	}
}

予め自動消滅させる座標を決めておき、変数dropPointに代入しておきます。
このスクリプトを適用したWallオブジェクトのX座標がdropPointを超えたらDestroy(gameObject)で
自動生成されたWallオブジェクトを消滅させます。

Floorオブジェクトに適用したマテリアルをスクロールするスクリプト


Playerとカメラが初期位置から動かなくなるため、Floorのマテリアルが静止しているとWallだけが
動いてくるように見えてしまい、Playerが飛んでいるように見えなくなってしまいます。
Wallの移動に合わせて、Floorのマテリアルもスクロールする必要があります。

GameController.cs

using UnityEngine;
using System.Collections;

public class Floor : MonoBehaviour {

	public float scroll = 0.15f;
	Renderer cRenderer;

	void Awake(){
		cRenderer = GetComponent<Renderer>();
	}

	void Update (){
		float x = Mathf.Repeat(Time.time * scroll, 1);
		Vector2 offset = new Vector2 (x, 0);
		cRenderer.sharedMaterial.SetTextureOffset ("_MainTex", offset);
	}

	public void Stop (){
		Destroy(this);
	}
}

14行目で、MathfクラスのRepeat関数を使用しています。
第1引数の値を第2引数の周期で繰返し、float型として返します。

19行目はスクロールを停止させるメソッドです。ゲームオーバー時に呼び出して使用します。
Destroy(this)と記述すると、スクリプトが停止します。
※Destroy(gameObject)と書いてしまうと、Floorオブジェクト自体が消えてしまうので注意しましょう。

まとめ


以上で障害物のWallオブジェクトが自動で生成され、スクロールするようになりました。
オブジェクトを無数に配置したりするとゲームの容量が増えてしまいますし、自動生成する場合でも
自動消滅の仕組みが無かったりするとメモリを消費し続けてしまうため、実行時の動作に悪影響を及ぼしかねません。
明確なゴールがない場合のゲームにはこのような繰返しのロジックが非常に有効です。

障害物の自動生成については以上です。
次回は ハイスコア機能の実装編 です。

最近よく読まれている記事

【新着】Unityで主観カメラへの切り替えと、プレイヤーの移動方法について
【注目】Unityでマウスホイールでカメラの向きにドリーイン・ドリーアウトさせる
【知らないと危ない】UnityのactiveSelfとactiveInHierarchyの違いについて
【鉄板】Unityでカメラの向きを基準に移動する方法と、追従して回転できるカメラの実装

Unityの記事一覧にもどる

  • このエントリーをはてなブックマークに追加

PAGE TOP