- 投稿日:2019-06-27T16:51:17+09:00
UnityでPhysics Materialを使わずにボールを跳ね返らせる
動機
Unityでビリヤードを作ろうとして、いつものようにPhysice MaterialのBounceを使おうとしたら、発射時の力が弱すぎてうまく跳ね返ってくれない事態が発生。
じゃあ自分で実装してみよう!ということに。反射ベクトルの求め方について
詳しいベクトルの解説はこちらや、
http://nn-hokuson.hatenablog.com/entry/2018/03/30/201715
こちらをご覧ください。
https://qiita.com/edo_m18/items/b145f2f5d2d05f0f29c9使う関数
リンク先ではずらずらと計算式が出てきたと思いますが、Unityでは一行で反射ベクトルを求められる便利関数が存在します。
Vector3 Reflect(Vector3 inDirection, Vector3 inNormal);この関数はinDirectionに物体のvelocity、inNormalに当たった物体の法線を与えてやれば、反射ベクトルを返してくれます。
実装
次に跳ね返させるオブジェクトを用意します。今回はSphereです。
RigidBodyをつけて、y軸だけ固定します。そして最初にボールを動かすために、velocityを変化させるスクリプトを書きます。
AddPower.csusing System.Collections; using System.Collections.Generic; using UnityEngine; public class AddPower : MonoBehaviour { private Rigidbody rb; private BounceCalc bounceCalc; public float power = 1; // 発射時の力 // Use this for initialization void Start () { rb = this.GetComponent<Rigidbody>(); bounceCalc = this.GetComponent<BounceCalc>(); } // Update is called once per frame void Update () { if(Input.GetKeyDown(KeyCode.Space)){ rb.velocity = new Vector3(power, 0, power); // 発射時のvelocityを取得 bounceCalc.afterReflectVero = rb.velocity; } } }次に、実際に反射ベクトルを計算しているスクリプトがこちらです。
BounceCalc.csusing System.Collections; using System.Collections.Generic; using UnityEngine; public class BounceCalc : MonoBehaviour { //ボールが当たった物体の法線ベクトル private Vector3 objNomalVector = Vector3.zero; // ボールのrigidbody private Rigidbody rb; // 跳ね返った後のverocity [HideInInspector] public Vector3 afterReflectVero = Vector3.zero; public void OnCollisionEnter (Collision collision) { // 当たった物体の法線ベクトルを取得 objNomalVector = collision.contacts[0].normal; Vector3 reflectVec = Vector3.Reflect (afterReflectVero, objNomalVector); rb.velocity = reflectVec; // 計算した反射ベクトルを保存 afterReflectVero = rb.velocity; Debug.Log ("nomal:" + afterReflectVero); } // Use this for initialization void Start () { rb = this.GetComponent<Rigidbody> (); } }この二つのスクリプトをSphereにアタッチするとBounceを使わなくてもボールが跳ね返ってくれます。