ここまででかなりVRシューティングテトリスの仕組みができてきました。
しかし、
- ブロックがどこに飛んでいくのかわかりにくい
- ブロックがたまにフィールドに引っ掛かってしまう
といったプレイする上で致命的な欠点が残っています。
特に、ブロックがフィールドに引っ掛かって誤動作を起こしてしまうのを防ぎたいですね。
前回の記事↓
ブロックが衝突する場所にポインタを表示させる処理
今回は、ブロックが衝突する場所が分かりやすくするようにポインタを表示させるようにします。
重力処理をなくす
まずは処理を簡単にするため、発射するブロックユニットの重力処理をなくして一直線に発射できるようにします。
BlockBazooka.csのFire()を下のように書き換えて重力処理をなくしましょう。
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 |
//ブロックを発射する関数 void Fire(Vector3 startPos, Vector3 direction, GameObject target) { //ブロックのコピーを生成させないようにコメントアウト // GameObject go = Instantiate(target); //重力を使用しない // rb.useGravity = true; var rb = target.GetComponent<Rigidbody>(); target.transform.parent = null; //ブロックの衝突判定を許可する for (int i = 0; i < target.transform.childCount; i++) { target.transform.GetChild(i).GetComponent<BoxCollider>().enabled = true; } //ブロックの発射位置を設定 target.transform.position = startPos; //ブロックをコントローラ正面方向に放つ target.GetComponent<Rigidbody>().AddForce(direction*10f,ForceMode.Impulse); //状態を「Wait」に変更 GameStatus.status = "Wait"; } |
衝突先を可視化
次に、ポインタのゲームオブジェクトを作成して、衝突先を可視化させていきます。まずは、ポインタのゲームオブジェクトを処理しやすくするため、BlockBazooka.csに以下を定義しましょう。
1 2 3 |
// ポインタオブジェクト [SerializeField] GameObject pointObj; |
そして、インスペクタの各コントローラのOVRControllerPrefabの子オブジェクトとしてSphereを生成しましょう。Scaleは0.05にしましょう。
生成したSphereを先ほど作成したFieldオブジェクトのPointObjに割り当てましょう。
そして、ポインタを可視化させるための関数ViewPointer()を追加します。この関数内では、Physics.RaycastAll()を使用して、コントローラの指す先の方向にぶつかったゲームオブジェクトをすべて取得するようにしています。ここで取得したい部分はFieldに当たった場合であるため、衝突したゲームオブジェクトの名前が”Field”のときpointObjの座標を変化させるように
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
void ViewPointer() { RaycastHit[] hits = Physics.RaycastAll(transform.position, transform.forward, 10f); if(hits.Length==0) { pointObj.SetActive(false); } else { pointObj.SetActive(true); foreach(RaycastHit hit in hits) { if(hit.collider.name=="Field") { pointObj.transform.position = hit.point; } } } } |
そして、GameStatusが「Shot」のときのみ、ViewPointer()を処理させるようにします。Field.csのUpdate()を以下のように書き換えましょう。
1 2 3 4 5 6 7 8 9 10 |
case "Shot": //ポインタを可視化 ViewPointer(); //A/Xボタンを押したらブロックを発射 if (OVRInput.GetDown(OVRInput.Button.PrimaryIndexTrigger, controller)) { // 以下略 break; |
この作業を右手と左手のコントローラの両方に割り当ててください。
この状態で実行してみましょう。
Field内の衝突する場所がポインタとして表示されている様子が確認できます。
【演出】ブロックが収まらない場合どこかへ飛んでいく処理
ここでは、演出を少し考慮していきます。
Field.csのOnCollisionEnter()ではめられないブロックを遠くへ飛ばす処理を実装していきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
void OnCollisionEnter(Collision other) { // // 省略 // //範囲外ならエラーを帰す if (bx < 0 || by < 0 || bx >= 10 || by >= 20 || CheckExistBlock(other.gameObject, bx, by)) { GameStatus.status = "Shot"; for (int i = 0; i < other.gameObject.transform.childCount; i++) { Destroy(other.gameObject.transform.GetChild(i).transform.GetComponent<BoxCollider>()); } other.gameObject.transform.GetComponent<Rigidbody>().AddForce(Vector3.back * 10f, ForceMode.Impulse); } else { // // 省略 // |
追加したAddForce()により、フィールドから跳ね返るような方向にブロックが飛んでいくように処理することができます。
1 |
other.gameObject.transform.GetComponent<Rigidbody>().AddForce(Vector3.back * 10f, ForceMode.Impulse); } |
では、この状態で実行してみましょう。ブロックが跳ね返る様子が確認できたでしょうか?
次回の記事↓
コメント