7
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

UnityちゃんがBlockを破壊して、しばらくしたら元に戻るようにする

Last updated at Posted at 2014-04-20

はじめに

前回に続きまして、
Blockを破壊して元に戻せるようにしてみます。

ロードランナーといえば、左右の足元のブロックをビーム?みたいなので削って、何故かしばらくすると復活するというのが最大の特徴かと思います。アニメーション的な効果はちょっとおいておいて、そうなるように作ってみます。

ビームは左右に出せるので、左=Z、右=Xを押した時にビームが出ることにします。

今回のポイント

  • 破壊できるBlockを特定する
    • Physics.Raycastを使う
    • Debug.DrawRay でRaycastを確認する
    • Layerを変更して余計なものにHitしないようにする
  • Blockを非表示にして、しばらくしたら元に戻す

破壊できるBlockを特定する

どのブロックが破壊できるか、を判定する方法はいくつかありそうですが、
せっかく?なのでUnityの中の当たり判定を最大限に使うことにします。

Raycastというのは、Ray(光線)をCast(投げかける)という意味合いなんだと思いますが、
一点から直線を引いてぶつかったObjectや地点を調べてくれる機能です。

大体の流れは以下のようになります。

  • ビームが出せるのは、「落ちていない」かつ「ZXを押しているとき」
  • Unityちゃんの頭上から斜め下45度にRaycast
  • HitしたのがBlockならば、HitGunメッセージをBlockに送る

以下の様なコードを、UnityChanDemo1.csUpdate()メソッドの下のほうに追加します。

hitgun
		// Gun
		int gun = Input.GetKey(KeyCode.Z) ? -1 : Input.GetKey(KeyCode.X) ? 1 : 0;
		if (gun != 0 && !isFalling) {
			RaycastHit hit;
			Vector3 fromPos = transform.position+Vector3.up;
			Vector3 direction = new Vector3(gun, -1, 0);
			float length = 1.8f;
			Debug.DrawRay(fromPos, direction.normalized * length, Color.green, 1, false);
			if (Physics.Raycast(fromPos, direction, out hit, length)) {
				if (canDestroyBlock(hit.transform)) {
					hit.transform.gameObject.SendMessage("HitGun");
				}
 			}
		}

同様にcanDestroyBlock()を追加します。

canDestroyBlockメソッド
	private bool canDestroyBlock(Transform block) {
		return 
			block.tag == BLOCK && 
			Mathf.Abs(block.position.x - transform.position.x) < 1.2f &&
			transform.position.y - block.position.y > 0.3;
	}

ちなみに UnityChanDemo1.cs の全体はこうなっています。

Physics.Raycast を使う

Physics.Raycast(始点、方向、Hit時にセットされるObject、判定する距離)

という感じに使います。
何かにHitしたら、戻り値がTrueになって、hitオブジェクトに値が入ります。

基本的には、このObjectのTagがBlockならば壊しても良いわけです。
ただ、高さの制約や、2つ向こうの側のBlockを消さないかという細かい条件もあるので、
実際に破壊できるかどうかは、canDestoryBlock()というメソッドで精査することにします。

壊せると判断すれば、そのObjectに足して SendMessage を使って HitGun メッセージを送ります。

Debug.DrawRay でRaycastを確認する

作っている最中におもったように判定がされない原因を調べたり、Raycastの微調整などをするときに実際のRaycast光線が見えると便利です。DrawRayを使うとそれが簡単にできます。

Debug.DrawRay(始点、方向、色、表示時間、depthTest [カメラから見えない場合に非表示にするか]))

というように使います。
ただ一つ注意があって、このDrawRayはGame Viewでは通常は表示されません。

Game Viewで表示するようにするには、 Gizmos というのを有効にする必要があります(これが最初わからなかった・・・)。下図の右上を押しておきましょう。

demo1_unity_-RoadRunner-_Web_Player.png

Layerを変更して余計なものにHitしないようにする

今回Unityちゃんの頭上から斜め下にRaycastをしているので、
実はBlockに当たる前にUnityちゃん自身にRaycastがぶつかってしまいます。
これだと本当に見つけたいBlockがわかりません。また、「はしご」「バー」に当たってしまうのも問題です。

なので、「Unityちゃん」「はしご」「バー」の3つのLayerを Ignore Raycast というLayerに割り当てます。
Raycastをするときは基本このLayerについて無視するようで今回は好都合です。

demo1_unity_-RoadRunner-_Web_Player_と_UnityちゃんがBlockを破壊して、しばらくしたら元に戻るようにする.png

もし複数のRaycastを管理するときは、Raycastの5番目の引数にもLayerMaskというのがあるのでこれが使えそうです(今回は使いませんが)。

Prefabに修正を適用する

ちょっと説明が遅れましたが、
PrefabからGameObjectに実体化したものの属性を変更(Layerの変更のような)した場合、InspectorのApplyボタンを押すとそれが大本のPrefabに反映され、その他全てのGameObjectに適用されます。便利ですね。

逆にRevertを押すと、GameObjectに修正が元のPrefabの属性で上書きされます。Selectを押すと元となっているPrefabが表示されます。

Blockを非表示にして、しばらくしたら元に戻す

全てが上手くいっていれば、Block オブジェクトにHitGunメッセージが送られています。
ただ、今はそれを処理するメソッドがないので、Consoleにはエラーが表示されます。

Blockにスクリプトを追加

BlockControl.cs というC# スクリプトを作り、Blockの 子供のCube に関連付けます。
実際の当たり判定(Collider)はこのCubeが持っているので、SendMessageの対象はこのCubeになります

demo1_unity_-RoadRunner-_Web_Player_と_UnityちゃんがBlockを破壊して、しばらくしたら元に戻るようにする.png

以下のような処理を追加します。

  • HitGunメッセージを受け取ったら、Timer をセットする。今回は180Frame(約3秒)とします。
  • Update()では、 Timerの値を一つずつ減らし、0ではない場合は collider(衝突判定), renderer(描画)を無効にする

とりあえずこれで意図通り動きました。

BlockControl.cs
using UnityEngine;
using System.Collections;

public class BlockControl : MonoBehaviour {
	private const int DISAPPEAR_TIMER_COUNT = 60*3;
	private int disappearTimer = 0;

	// Use this for initialization
	void Start () {
	}
	
	// Update is called once per frame
	void Update () {
		if (disappearTimer > 0) {
			disappearTimer--;
		}
		renderer.enabled = collider.enabled = disappearTimer == 0;
	}

	void HitGun() {
		if (disappearTimer > 0) {
			return;
		}
		disappearTimer = DISAPPEAR_TIMER_COUNT;
	}
}

さいごに

一応上手く?やるとUnityちゃんがBlockに挟まって動けなくなりますw

Blockが壊れる・元に戻るというのもアニメーションさせたいですね。
アニメーションの課題は山積みです。。。

今回のものはここからWebPlayerで見られます

ソースコードはGithubに公開しています

7
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?