Unity入門記録 02

ブロック崩しの続き

前回から引き続きチュートリアルのブロック崩しを作っていきます。

ただ、本家のチュートリアルの続きが無いので自分で考えながらです。(日本語しか見てないので、英語版は用意されているのかもしれませんが)

まずはブロックの用意

前回の成果物に圧倒的に足りないもの。

そう、ブロック

壁を作ったのと同様にしていけば問題ないでしょう。

Blocks

こんな感じで配置していきます。

これだけで、ボールはブロックに跳ねるようになります。

各ブロックは、Empty Objectを作ってそこに入れていくと管理しやすいでしょう。

Empty Objectはフォルダみたいなものでしょうか。AfterEffectやっている人はNullObjectの概念が非常に近い感じです。

AS3やObjective-C、JS(DOM)だとそれぞれSprite, UIView, divみたいなものを意識するといいかもしれません。

これだけではブロックは消えたりしないので、ボールとの当たり判定を見て自分でブロックを消す必要がありそうです。

Unityにおいての当たり判定の取り方を調べれは良さそうです。

オブジェクト同士の当たり判定を取る

調べてみると、オブジェクト同士が衝突した際に、Rigidbody(前回ボールに設定した)のOnCollisionEnter(col : Collision)メソッドが呼ばれるらしいです。

UnityのCollisionオブジェクトというのがわからないので調べてみると、衝突という意味みたいです。そのままですね。

Collisionには衝突の情報として、衝突対象のGameObjectが格納されてるっぽいので、そのオブジェクトをOnCollisionEnterの中で削除すれば良さそうです。

オブジェクトの削除方法も調べてみました。

Destroy(GameObject)というメソッドを使えばいいっぽいです。

まとめると

function OnCollisionEnter(col:Collision) {
    Destroy(col.gameObject);
}

でしょう。

これを前回のBallControllerに追加してみることに。

#pragma strict

var speed = 5;

function Start () {
	rigidbody.AddForce((transform.forward + transform.right) * speed, ForceMode.VelocityChange);
}

function Update () {

}

function OnCollisionEnter(col:Collision) {
    Destroy(col.gameObject);
}

これがコード全体です。実行してみます。

Unity WebPlayerが必要です。

おしい。

このままだと無差別殺人なので、当たった対象がブロックかどうか調べる必要がありそうです。

オブジェクトを見分ける

どうやってオブジェクトを見分けるか考えてみました。

col.gameObject.nameでhierarchyパネル上でつけた名前が取得できることはわかったので、ブロック全部に同じ名前をつけてそれで判別してもいいのですが、ブロックなどの当たり判定対象が増えてきた時に大変な事になりそうです。

今回ブロックはすべてBlocksという名前をつけたEmptyObjectに入れたので col.gameObjectBlocksの子かどうか知る方法はないか調べてみることに。

(gameObject).transform.IsChildOf(gameObject)というメソッドがあったので、多分これが使えます。

なんでtransformに子を調べたりするメソッドが入っているのかよくわかりません。ドキュメントを後で読んできます。

とりあえず今回は、Blocks.transform.IsChildOf(col.gameObject)で衝突したオブジェクトがBlocksの子かどうか分かりそうです。

が、実際はこのコードダメだった

is child Of hogeなのでhogeの子ですか?って意味のメソッドぽくて、

col.gameObject.transform.IsChildOf(Blocks);

が正解。

肝心のBlocksオブジェクトの取得方法ですが、GameObject.Findという関数を使えば実現できそうです。

今回はhierarchy直下にBlocksを配置しているので、

var blocks = GameObject.Find('/root/Blocks');

で取得できるはずです。

と、思ったんだけどできませんでした。

/root から辿れるって書いてある気がするんだけど、取得できませんでした。勘違いしてるみたいです。

GameObjectのたどり方は結構重要そうな気がするので、調べがいがありそう。

結局

var blocks = GameObject.Find('Blocks');

で、取得出来ました。納得はしていない。

ということで、全体のコードが以下です。

#pragma strict

var speed = 5;

function Start () {
	rigidbody.AddForce((transform.forward + transform.right) * speed, ForceMode.VelocityChange);
}

function Update () {

}

function OnCollisionEnter(col:Collision) {
    var blocks = gameObject.Find("Blocks");
    if (col.transform.IsChildOf(blocks.transform)) {
    	Destroy(col.gameObject);
    }
}

これをビルドすると以下のようになります。

game

Unity WebPlayerが必要です。

あと少しで完成しそうですが、疲れたので次にします。

今回のソースもgithubにあげてあります。

practice02タグを見て下さい。

ゲームオーバーはどうする?

同じように、枠の下側のCubeとの当たり判定を見ればいいでしょう。

ゲームクリアはどうする?

Blocksの子が0になったらゲームクリアにできそう。

そのあと、ボールを止めたりシーンを遷移させたりすると完成かも。

今回のまとめと所感

  • GameObjectの取得は重要そうだ
  • Ballが他のObjectを操作するのはイケてない感じがする
  • プログラミング作法的な話は後でいいや
  • JSで書いてるっぽいけど、他の言語使えたよね???