【Unity】【物理】ベルレ法で物体に力を加える

ベルレ法を使って物体に力を加えた結果の位置を計算する方法です。

ベルレ法?

ベルレ法とは現在の位置と1フレーム前の位置から1フレーム後の位置を計算するための手法です。

位置を求めるときにはよく初期位置を使ったりしますが、
この方法では初期位置がわからなくても計算できます。

前フレームの位置を{p_{-1}}、今の位置を{p_0}、deltaTimeを{h}
今掛かっている力を{f}、質量を{m}とすると、
次フレームの位置{p_1}は下記の式で求められます。

 { \displaystyle
p_1 = p_0 + (p_0 - p_{-1}) + \frac{h^{2}}{m}f
}
※ deltaTimeは変わらないとする

実装

実装はこんな感じです。

using UnityEngine;

public class Verlet : MonoBehaviour
{
    [SerializeField, Tooltip("質量")]
    private float _mass = 1.0f;
    [SerializeField, Tooltip("クリック時にかかる力の大きさ(N)")]
    private float _force = 500;

    private Vector3 _previous;

    private void Awake () 
    {
        _previous = transform.position;
    }
    
    private void Update ()
    {
        if (Input.GetMouseButtonUp(0)) {
            // 上向きの力を適用
            Update(Vector3.up * _force, Time.deltaTime);
        }
        else {
            // 重力を適用
            Update(Vector3.down * 9.8f * _mass, Time.deltaTime);
        }
    }

    private void Update(Vector3 force, float deltaTime)
    {
        var currentPos = transform.position;
        var tmp = currentPos;

        // ベルレ法で次の位置を求める
        currentPos = 2 * currentPos - _previous + force * deltaTime * deltaTime / _mass;

        // 移動制限を適用する
        if (currentPos.y < 0) {
            currentPos.y = 0;
        }

        transform.position = currentPos;
        _previous = tmp;
    }
}

結果

前節のスクリプトを適当なオブジェクトにアタッチして再生します。
クリックすると上向きに_forceニュートンの力が加わります。

f:id:halya_11:20180723205928g:plain

参考

式は下記のサイトを参考にさせていただきました。
(ちゃんとした式は下記のサイトをご覧ください)

himaxoff.blog111.fc2.com