9
6

More than 5 years have passed since last update.

UnityでPhysics Materialを使わずにボールを跳ね返らせる

Posted at

動機

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

9
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
6