Unity入門記録 02
ブロック崩しの続き
前回から引き続きチュートリアルのブロック崩しを作っていきます。
ただ、本家のチュートリアルの続きが無いので自分で考えながらです。(日本語しか見てないので、英語版は用意されているのかもしれませんが)
まずはブロックの用意
前回の成果物に圧倒的に足りないもの。
そう、ブロック。
壁を作ったのと同様にしていけば問題ないでしょう。
こんな感じで配置していきます。
これだけで、ボールはブロックに跳ねるようになります。
各ブロックは、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);
}
これがコード全体です。実行してみます。
おしい。
このままだと無差別殺人なので、当たった対象がブロックかどうか調べる必要がありそうです。
オブジェクトを見分ける
どうやってオブジェクトを見分けるか考えてみました。
col.gameObject.name
でhierarchyパネル上でつけた名前が取得できることはわかったので、ブロック全部に同じ名前をつけてそれで判別してもいいのですが、ブロックなどの当たり判定対象が増えてきた時に大変な事になりそうです。
今回ブロックはすべてBlocks
という名前をつけたEmptyObjectに入れたので
col.gameObject
がBlocks
の子かどうか知る方法はないか調べてみることに。
(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);
}
}
これをビルドすると以下のようになります。
あと少しで完成しそうですが、疲れたので次にします。
今回のソースもgithubにあげてあります。
practice02
タグを見て下さい。
ゲームオーバーはどうする?
同じように、枠の下側のCubeとの当たり判定を見ればいいでしょう。
ゲームクリアはどうする?
Blocks
の子が0
になったらゲームクリアにできそう。
そのあと、ボールを止めたりシーンを遷移させたりすると完成かも。
今回のまとめと所感
- GameObjectの取得は重要そうだ
- Ballが他のObjectを操作するのはイケてない感じがする
- プログラミング作法的な話は後でいいや
- JSで書いてるっぽいけど、他の言語使えたよね???