20190627のUnityに関する記事は1件です。

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に当たった物体の法線を与えてやれば、反射ベクトルを返してくれます。

実装

まず適当にステージを作ります。
Unity 2017.4.18f1 Personal (64bit) - PhysicsTest.unity - Syogikuzushi - Universal Windows Platform_ _DX11_ 2019_06_27 16_28_31 (2).png

次に跳ね返させるオブジェクトを用意します。今回はSphereです。
RigidBodyをつけて、y軸だけ固定します。

qiita_sphere (2).png

そして最初にボールを動かすために、velocityを変化させるスクリプトを書きます。

AddPower.cs
using 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.cs
using 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を使わなくてもボールが跳ね返ってくれます。

ezgif.com-video-to-gif.gif

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む