今回は、コントローラからブロックを発射する処理と、フィールドにくっつける処理を作成していきます。
前回の記事↓
【事前準備】左右のコントローラの識別方法
まずは事前準備として、左右のどちらのコントローラかを識別させるための方法について説明していきます。(少し長いため、この章を飛ばして作っていく中で理解しても問題ありません)
OVRでは、コントローラの種類を識別させるために、OVRInput.Controllerクラスというものがあります。これは、第1回で右コントローラにR Touchを、左コントローラにL Touchを設定したものです。これは、各コントローラのインスペクタにあるOVR Controller Helperの中のm_controller変数に格納されています。これを使って、コントローラのm_controllerがL Touchのとき左コントローラ、R Touchのとき右コントローラと識別させることができます。
この処理を使うと、OVRInput.GetButton(OVRInput.Button.One, controller)関数により右コントローラではAボタンを押しているかどうか、左コントローラではXボタンを押しているかどうかの処理になります。この関数が優れている点は、左右で別々のコードを書かずに済むようになるという点で、開発がとても楽になります。
(図はOVRInputに関する公式リファレンスより引用)
ボタンの割り当てなども詳しくは、公式リファレンスに載っているため、確認してみてください。
それでは、次の章から実装の説明に入ります。
ブロックを発射する処理
まずは、前回の画面がこちらになります。
今回は、コントローラからブロックを放つため、ヒエラルキーからはブロックを削除してください。
スクリプトの作成
それでは、コントローラに追加するコンポーネントを作成していきます。
まずは、Scriptsフォルダを作成してください。
Scriptsフォルダ内に、BlockBazookaというスクリプトを作成してください。
そして、BlockBazookaを右手コントローラ(OVRControllerPrefab)のインスペクタ―にドラッグ&ドロップしてください。
BlockBazooka.csの実装
ではBlockBazookaのコードを作成していきましょう。
次のコードを書いてください。
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 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class BlockBazooka : MonoBehaviour { // ブロックのゲームオブジェクト [SerializeField] GameObject blockObj; // 左右どちらのコントローラかを取得するために使用するControllerクラス OVRInput.Controller controller; // Start is called before the first frame update void Start() { // 左右どちらのコントローラかを取得 controller = GetComponent<OVRControllerHelper>().m_controller; } // Update is called once per frame void Update() { //A/Xボタンを押したらブロックを発射 if(OVRInput.GetDown(OVRInput.Button.One,controller)) { Fire(transform.position,transform.forward,blockObj); } } //ブロックを発射する関数 void Fire(Vector3 startPos, Vector3 direction, GameObject target) { //ブロックのコピーを生成 GameObject go = Instantiate(target); //ブロックの発射位置を設定 go.transform.position = startPos; //ブロックをコントローラ正面方向に放つ go.GetComponent<Rigidbody>().AddForce(direction*10f,ForceMode.Impulse); } } |
変数の説明
まず、変数の説明に入ります。
blockObjはブロックのゲームオブジェクト用の変数として定義して、プレハブのブロックを入れられるようにするためSerializedFieldの属性をつけています。
OVRInput.Controllerクラスのcontrollerは、左右のどちらのコントローラかを識別できるようにするため定義します。設定は、Start関数に「 controller = GetComponent<OVRControllerHelper>().m_controller;」の一行を書くことで実装しています。
関数の説明
次に、Update関数内の説明に入ります。Update関数内では、Aボタンを押したときにブロックを発射するFire関数を実行するように記述しています。このif分岐で使用している「OVRInput.GetDown(OVRInput.Button.One,controller)」は、第一引数にボタンの割り当てを、第二引数にどのコントローラかを記述することで、第二引数のコントローラの第一引数のボタンを押しているかどうかを検知できる関数です。今回は第一引数にButton.Oneを、第二引数にR Touchを指定していることになるため、「右手のコントローラのAボタンを押しているかどうか」を検知していることになります。
最後のFire関数の説明に入ります。Fire関数では、コントローラの位置にブロックを生成して、コントローラの向いている方向に放つといったコードを記述しています。
ここまで書いたら、Unityの画面に戻ってください。
プレハブのブロックのインスペクタからRigidbodyを追加してください。追加方法は下部のAdd ComponentからRigidbodyを探して追加です。
また、BlockBazookaのblockObjにプレハブのブロックをドラッグ&ドロップしてください。
これで準備は完了です。
この状態で実行すると、下のようにコントローラからブロックが放たれる様子が確認できます。
フィールドにブロックをくっつける処理
次に、フィールドにブロックをくっつける処理を作成していきます。現在は、フィールドの端のみ衝突判定が設定されているため、中身のみ衝突判定が設定されるように実装していきます。
まずは、 FieldのインスペクタからBox Colliderを追加してください。
追加したBox Colliderの設定は以下のようにしてください。だいたいフィールドの枠内の領域になります。
さらに、枠自体に衝突判定を加えないようにするため、「Bottom」「Right」「Left」のBox Colliderのラベル左にあるチェックは外しておいてください。
また、この状態で実行するとフィールドが近すぎてしまうため、FieldのPositionのz座標を5に設定してください。ちなみに、ここで5と設定するとユーザからフィールドまでの距離が5mに設定されます。遠すぎると感じたらここの数値を調整してみてください。 では、この状態で実行してみましょう。
フィールド内にブロックを当てると衝突して下に落下する様子が確認できると思います。(ちなみに、GameウインドウとSceneウインドウは下の画面のように並べて表示できます。)
スクリプトの作成
それでは、ここからは衝突したブロックがフィールドに固定されるような処理を加えていきましょう。
まずはScriptsフォルダ内にFieldという名前のスクリプトを作成してください。
作成したら、必ずゲームオブジェクトのFieldにこのスクリプトを追加しておきましょう。
Field.csの実装
では、Fieldのスクリプトを記述していきます。
以下のコードを記述してください。
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 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Field : MonoBehaviour { // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { } void OnCollisionEnter(Collision other) { // Rigidbodyを取得 var rb = other.gameObject.GetComponent<Rigidbody>(); // Rigidbodyを削除→ブロックに物理演算がなくなる→フィールドにくっつく Destroy(rb); } } |
今回は、衝突判定のみ使用するため、OnCollisionEnter関数を使用します。この関数は、Unity特有の関数であり、「何かオブジェクトが衝突した瞬間に起動する」関数です。第一引数のotherには衝突したゲームオブジェクトが自動的に渡されます。
今回は、「衝突したゲームオブジェクトの物理演算をなくした」ため、この関数内には、otherのrigidbodyを取得して、Destory関数によりrigidbodyを削除するといった処理を記述していきます。Rigidbodyを削除するということは、物理演算をなくすことと同じなため、衝突した瞬間その場で停止するようになります。つまり、実装したいフィールドにぶつかったブロックをくっつける処理になります。
それでは、この状態で実行してみましょう。下のようにフィールドにぶつかったブロックがくっついている様子が確認できれば成功です。
次回予告
次回は、フィールドの細かい部分の実装とくっつけたブロックをフィールドのマスに自動的に合わせる処理を実装していきます。
次回の記事↓
コメント