自動ドアの制御(2) Ray casting

Unity勉強会用の資料として。
自動ドアの制御の3つのやり方、その2。

—————————————————
3つの衝突判定
・Collision Detection [detecting]:コライダーがぶつかっているかどうかで判定。
・Ray Casting [drawing]:コライダーがぶつかる前に、ベクターで対象を検知。
・Trigger Collision Detection [detecting]:コライダーの領域内にもう1つのコライダーが重なっているかどうかで判定。
—————————————————

Approach 2 : Ray casting

Screen-Shot-2013-09-13-at-23.42

デモはこちら。

コライダーがぶつかる前に、ベクターで対象を検知。
特徴:一定の距離に近づき、ドアの方向を向くと、ドアが開く。
欠点:ドアの方向を向かないと開かない。

—————————————————
スクリプト ‘DoorManager’ をドアに適用。

—————————————————
スクリプト ‘PlayerCollisions’ をプレイヤーに適用。

C# の ‘out’ パラメータについて。
http://msdn.microsoft.com/en-us/library/ee332485.aspx
・参照渡し ⇔ 値渡し

自動ドアの制御(1) Collision Detection

Unity勉強会用の資料として。
自動ドアの制御の3つのやり方、その1。

—————————————————
3つの衝突判定
・Collision Detection [detecting]:コライダーがぶつかっているかどうかで判定。
・Ray Casting [drawing]:コライダーがぶつかる前に、ベクターで対象を検知。
・Trigger Collision Detection [detecting]:コライダーの領域内にもう1つのコライダーが重なっているかどうかで判定。
—————————————————

Approach 1 : Collision detection

Screen-Shot-2013-09-13-at-23.42

デモはこちら。

コライダーがぶつかっているかどうかで判定。
特徴:ドアに接触すると、ドアが開く。
欠点:ぶつからないとドアが開かない。

—————————————————
スクリプト ‘PlayerCollisions’ をプレイヤーに適用する。

Learn Unity 4 for iOS Game Development 9

ゲーム GUI

作ったもの
・ボウリング・ゲームへのスコアボード/メニュー画面/ポーズ機能の実装(エスケープキーで、一時停止できます)。

クリックすると、別ウィンドウが開きます。(音が出ます。)
Screen-Shot-2013-08-18-at-15.05_600
http://shakeweb.sakura.ne.jp/demo/LU4_chap9/

————————————————————————————————
スコアボードの実装

・シーンにスコアボード用の空の GameObject を用意して、スクリプトを適用する。

・GUI クラスのラベルにテキストで表示。

————————————————————————————————
メニュー画面/一時停止機能の実装

・一時停止機能が付いていないと、アップルの審査に落とされることがある。
・メニュー画面/一時停止機能用の空の GameObject を用意して、スクリプトを適用する。

・FSM と同じように、それぞれのページのステートを用意する。

・Time.timeScale をゼロにすると、ゲーム中の動きが止まる。反対に、保存しておいた元の timeScale に戻すと、動き出す。同様に、timeScale の値を見れば、停止しているかどうか判定できる。

・ゲーム開始時に、ゲームを一時停止させ、メニュー画面を表示させる。

・escape キーで、’一時停止’/’停止解除’/’サブメニュー画面からのメインメニュー画面への遷移’を制御できるように、Update() 関数でキーボード入力を監視する。

・一時停止中は Time.deltaTime の値がゼロになり、ゼロで割るエラーを引き起こしてしまうので、ボールの動きを制御するスクリプトを修正する。

・メニュー画面の表示を OnGUI() 関数で制御。

・OnGUI() コールバックは、1フレーム中に複数回呼び出されるので、一時停止中かどうか、常に監視される。

・GUILayout クラスの BeginArea() 関数で GUI の表示領域の指定を開始し、EndArea() 関数で終了する。

・GUILayout.Button(“Back”) は、これ自体でボタンを表示させ、ボタンが押されたら、戻り値が true になる。尚、この関数は、一時停止中は OnGUI() 関数経由で常に監視され続ける。

・メインメニュー表示。

・一時停止中は、OnGUI() 関数経由で常に監視され続ける。ボタンが押されると、OnGUI() の switch 文で別ページに遷移する。

・クレジット・ページ。

・オプション・ページ。

・GUILayout.Toolbar に渡す toolbarStrings で、ボタンに表示する名前を指定。toolbarIndex で選択されているボタンを指定。また、この関数は選択されているボタンのインデックスを int 型で返す。ShowOptions() 関数は、OnGUI() 経由で常に監視されているので、ボタンが選択されると、すぐさま、インデックスの値が変数 toobaIndex に代入され、Toolbar() に渡される値に反映されて、表示が切り替わる。

・オーディオ・パネル。

・グラフィクス・パネル

・QualitySettings.GetQualityLevel() が int 型で値を返すので、それをインデックスとして配列 name から表示する名前を引っ張ってくる。

・システム・パネル。

・Available() がエラーになるため、使用を断念。Unity Pro なら使えるのだろうか。

————————————————————————————————
アセットストア(GUI 関連)

EZGUI (Above and Beyond Software)
NGUI (Tasharen Entertainment)

Learn Unity 4 for iOS Game Development 8

レッツ・プレイ! ゲーム・スクリプティング

作ったもの
・ボウリング・ゲームへの、ゲーム・ロジックの実装。

クリックすると、別ウィンドウが開きます。(音が出ます。)
Screen-Shot-2013-08-16-at-17.42_600
http://shakeweb.sakura.ne.jp/demo/LU4_chap8/

————————————————————————————————
・FSM(finite state machine)の概念に則って、汎用的にスコアを計算するためのクラス郡を収めたライブラリ用の .js ファイルを用意する。

————————————————————————————————
フレームごとのスコアを保持するクラス

・スペア/ストライク時、以降のフレームが終了するまでスコアが未確定の場合は、-1 とする。

————————————————————————————————
スコアを計算するクラス

・クラス内に、変数、コンストラクタ、スペア/ストライク判定用関数を用意。

・scores:FuguBowlScore[] : built-in array : 処理は早いが、一度作るとリサイズできない。
・コンストラクタで、配列 scores を用意し、10フレーム分のスコアを初期化して未確定にしておく。
・各フレームのスペア、ストライク判定用の関数 IsSpare()、IsStrike() を用意。
・FuguBowlPlayer クラスは、FuguBowlScore クラスのラッパーのようなもの。

・スペア/ストライク時のスコア更新用関数を用意。

・スペア時 : 10(1投目 + 2投目)+ 次のフレームの最初の投球。
・ストライク時 : 10(ストライク)+ 次のフレームの最初の投球 + 次の投球。

・1投目のスコア確定用関数。

・2投目のスコア確定用関数。

・3投目のスコア確定用関数。

・総合得点取得用関数。

・recursive function : 自分自身を呼ぶ関数。

————————————————————————————————
・ピンが倒れているかどうかを判別するスクリプトをそれぞれのピンに適用する。

————————————————————————————————
ゲーム・コントローラーに処理を追加

・FuguBowlPlayer をインスタンス化。

・倒れているピンの数をカウントする。

・倒れたピンを非表示にする。

・SetActive(false) で、GameObject を非アクティブにできる。

・ResetPins 関数に非アクティブにしたピンを再度、アクティブにする処理を追加。

————————————————————————————————
FSM (finite state machine)

・ゲーム進行を整理する。
 New Game
 ↓ ※
 Ball1 || Ball2 || Ball3
 Rolling
 RolledPast || GutterBall
 Roll Over
 Spare || Strike || KnockedSomeDown
 NextBall
 ↓(最終フレームが来るまで ※ に戻る)
 GameOver

・現在のフレーム数と何投目かを入れる変数を用意。

・前章で用意した Update() 関数を削除し、代わりに Start() 関数内でコルーチンを使用して FSM を実装する。
・それぞれのステートに合わせた処理を、コルーチンとして呼び出す。

・yield で処理を明け渡した上で StartCoroutine() でコルーチンを実行し、while 文のループを一時停止させる。
・コルーチンと yield について リファレンス

・ゲーム開始時のステート、StateNewGame の処理。

・1投目のステート、StateBall1 で投球前の初期化処理。

・2投目のステート、StateBall2 で投球前の初期化処理。

・3投目のステート、StateBall3 で投球前の初期化処理。

・投球後のステート、StateRolling の処理。

・yield で処理を明け渡した上で、while 文をループさせ続け、条件を満たした時に処理を抜ける。

・投球後、ボールがピンのラインを越えた時のステート、StateRolledPast の処理。

・SmoothFollow 型や MonoBehaviour 型の変数に代入しても、enabled / disabled を切り替えられるが、汎用性を考慮して、Behaviour 型に代入。
 Behaviour クラス → MonoBehaviour クラス → SmoothFollow 等の GameObject に適用されたスクリプトのクラス。
・l.6では GetComponent() にクラス名を渡しているのに対し、l.2ではストリングを渡している。
 l.2 GetComponent(“SmoothFollow”) : ランタイムエラー
 l.6 GetComponent(FuguForce) : コンパイラエラー
 SmoothFollow クラスは、Unity の開発環境によっては、存在しない可能性もあり得る。
 存在しないクラスの enabled 変数にアクセスしようとすれば、エラーになる。
 ストリングを渡せば、同名のコンポーネントが見つからない場合は、ランタイム時に null が返ってくるため、null チェックができる。
・yield WaitForSecontds() で処理を明け渡した上で、5秒間、一時停止させる。

・disabled にされたコンポーネントを、リセット時に、再度、enabled にする。

・ガター時のステート、StateGutterBall の処理。

・ガター時/ボールがピンのラインを越えた時のステート、StateRollOver の処理。

・投球後の結果の各ステート、StateSpare、StateStrike、StateKnockedSomeDown の処理。

・投球完了時のステート、StateNextBall の処理。

・ゲームオーバー時のステート、StateGameOver の処理。

————————————————————————————————
参考アセット

FSM のアセット
Playmaker (Huton Games)

————————————————————————————————
FSM に関連した参考サイト

CryEngine 3 Free SDK
Entity States を検索。

Blue Mars wiki
entity script を検索。

Second Life wiki
state を検索。

Learn Unity 4 for iOS Game Development 7

レッツ・ボウル! 物理学応用編

作ったもの
・ドラム缶を倒す、ボウリング・ゲーム。
・マウスカーソルを移動させると、ボールがその方向へ転がります。

クリックすると、別ウィンドウが開きます。(音が出ます。)
Screen-Shot-2013-08-14-at-13.26_600
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本。

・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 に適用する。

————————————————————————————————
ゲーム・コントローラー(続き)

・戻り値を必要としない場合は、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。

————————————————————————————————
ピンがぶつかる時の音の制御する

・ピンとそれにぶつかるもの(ボール、他のピン)は動いているので、velocity の代わりに relativeVelocity を使用する。

————————————————————————————————
使用アセット

Barrel (Universal Image)
Free SFX Package (Bleep Blop Audio)

————————————————————————————————
関連リンク

3Dモデル・マーケットプレイス
http://Turbosquid.com

フリー・オーディオ素材
http://freesound.org

ページトップへ