Learn Unity 4 for iOS Game Development 7
レッツ・ボウル! 物理学応用編
作ったもの
・ドラム缶を倒す、ボウリング・ゲーム。
・マウスカーソルを移動させると、ボールがその方向へ転がります。
クリックすると、別ウィンドウが開きます。(音が出ます。)
http://shakeweb.sakura.ne.jp/demo/LU4_chap7/
————————————————————————————————
床を拡張する
・Transform コンポーネントの Local Scale でサイズを変更するのは望ましくない。サイズを変えたい場合は、Import Settings ですること。どうしても Transform で変える場合は、x、y、z、それぞれ均等に値を変更する。
————————————————————————————————
ゲーム・コントローラー
・ピンの prefab を作成し、スクリプトで配置する。1列目に1本、2列目に2本、3列目に3本、4列目に4本の計10本。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
#pragma strict #pragma downcast var pin:GameObject; // pin prefab to instantiate var pinPos:Vector3 = Vector3(0,1,20); // position to place rack of pins var pinDistance = 1.5; // initial distance between pins var pinRows = 4; // number of pin rows var ball:GameObject; // the bowling ball var sunkHeight:float = -10.0; // global y position which we call a gutterball private var pins:Array; function Awake () { CreatePins(); } function CreatePins () { pins = new Array(); var offset = Vector3.zero; for (var row=0; row < pinRows; ++row) { offset.z += pinDistance; offset.x = - pinDistance * row/2; for (var n=0; n <= row; ++n) { pins.push(Instantiate(pin, pinPos + offset, Quaternion.identity)); offset.x += pinDistance; } } } function Update () { if (ball.transform.position.y < sunkHeight) { ResetEverything(); } } function ResetBall() { ball.SendMessage("ResetPosition"); } function ResetPins() { for (var pin:GameObject in pins) { pin.BroadcastMessage("ResetPosition"); } } function ResetCamera () { Camera.main.SendMessage("ResetPosition"); } function ResetEverything () { ResetBall(); ResetPins(); ResetCamera(); } |
・rotation は、Euler angle(x,y,z)ではなく、Unity の内部処理で使われている Quaternion(四元数、w,x,y,z)を使用。
Transform.rotation、Transform.rocalRotation : Quaternion
Transform.eulerAngles、Transform.localEulerAngles : Euler angles
・Instantiate は、Object クラスの静的関数。Instantiate = this.Instantiate。しかし、Object.Instantiate と呼ぶことはできない(Mono でも Object クラスが定義付けられているため。JavaScript のみ)。代わりに UnityEngine.Object.Instantiate を使用する。
System.Object : Mono(こちらが先に参照される)
UnityEngine.Object.Instantiate : Unity
・Awake は、スクリプトが有効になっているかどうかに拘らず、Start より先に、1度だけ呼ばれる。(初期化に適している。)
・空の GameObject をシーンに配置し、そこにコントローラー・スクリプトを適用する。
・ピンが倒れるように Rigidbody コンポーネントと、PhysicMaterial を適用する。
————————————————————————————————
ボールが床から落下した時の処理
・リセット用のスクリプトを、ボール、メインカメラ、ピンの prefab に適用する。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#pragma strict private var startPos:Vector3; private var startRot:Vector3; function Awake () { // save the initial position and rotation of this GameObject startPos = transform.localPosition; startRot = transform.localEulerAngles; } function ResetPosition () { // set back to initial position transform.localPosition = startPos; transform.localEulerAngles = startRot; // make sure we stop all physics movement if (rigidbody != null) { rigidbody.velocity = Vector3.zero; rigidbody.angularVelocity = Vector3.zero; } } |
————————————————————————————————
ゲーム・コントローラー(続き)
・戻り値を必要としない場合は、SendMessage で関数を実行できる。
・BroadcastMessage は、子の GameObject にも送信できる。
・#pragma strict だけだと警告がでるので、#pragma downcast を追加する。Array が Object で定義されているにも拘らず、要素が GameObject として扱われているため。Object のサブクラス GameObject に downcast してやる。
・インポートした Barrel アセットの子 GameObject に、Capsule Collider と Box Collider コンポーネントを適用し Barrel の形に沿った Collider を用意する。
・GameObject | Apply Changes To Prefab で変更を prefab に反映させる。
————————————————————————————————
ボールが転がる音の制御
・ボールが転がる効果音の AudioSource を Ball に適用し、スクリプトで再生タイミングを制御する。メインカメラに AudioListener。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
#pragma strict var minSpeed:float = 1.0; private var sqrMinSpeed:float = 0; function Awake() { sqrMinSpeed = minSpeed * minSpeed; } function OnCollisionStay( collider:Collision) { if(rigidbody.velocity.sqrMagnitude > sqrMinSpeed) { if(!audio.isPlaying) { audio.Play(); } } else { if(audio.isPlaying) { audio.Stop(); } } } function OnCollisionExit(collider:Collision){ if(collider.gameObject.tag == "Floor") { if(audio.isPlaying) { audio.Stop(); } } } |
————————————————————————————————
ピンがぶつかる時の音の制御する
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#pragma strict var minSpeed = 0.01; // actually the square of the minSpeed function OnCollisionEnter (collider:Collision) { if(collider.relativeVelocity.sqrMagnitude > minSpeed) { if(collider.gameObject.tag != "Pin") { audio.Play(); // hit anything besides another pin, play the sound } else { // otherwise pin with lower ID gets to play if(gameObject.GetInstanceID() < collider.gameObject.GetInstanceID()) { audio.Play(); } } } } |
・ピンとそれにぶつかるもの(ボール、他のピン)は動いているので、velocity の代わりに relativeVelocity を使用する。
————————————————————————————————
使用アセット
Barrel (Universal Image)
Free SFX Package (Bleep Blop Audio)
————————————————————————————————
関連リンク
3Dモデル・マーケットプレイス
http://Turbosquid.com
フリー・オーディオ素材
http://freesound.org