[Unity]複数オブジェクトを連動して動かすAddForceの使い方

Unity
https://amzn.to/3bd8XOX

 前回に引き続き物理演算でそろばんを再現しようと悪戦苦闘しています。前回は珠が一つで期待する動きとなっていました。今回は珠を増やして動かした時の挙動についてご紹介します。いつもは問題が解決してから記事にまとめているのですが、今回は調査しながらなので、うまく着地できるか不安です

Goal

複数のそろばん珠を制御して、そろばんっぽく動かす!




たまを2つに増やした時の挙動

 これまで、珠一つで下から上へ動かした時、壁に当たってぴたりと止まることを確認しています。これはスクリプトで珠にインパクトを加えて、衝突により止まることを確認した時の動きです。スクリプトなどはこちらをご覧ください。

 今回、この動きを二つの珠でやってみました。そろばんのように並べて、下の珠から力を加えて2つ同時に動かしました。すると、どういうわけか、壁に衝突後、跳ね返って二つとも落ちてきました。重力は無効にしてあります。

物理マテリアルを設定してみる

 物理マテリアルを設定していなかったので、反発係数によるものかと思い、壁、2つの珠にそれぞれ以下の物理マテリアルを設定して動きを見てることにしました。ちなみに物理マテリアルはそれぞれ以下の意味を持ちます。

プロパティ 機能
Dynamic Friction 移動している物体に対する摩擦。通常は、0 から 1 の間の値を使用します。0 の場合、氷のような感じになります。1 の場合、強い力や重力がオブジェクトを押さない限り、すぐに止まります。

Static Friction

面上で静止しているオブジェクトに使用される摩擦。通常は、0 から 1 の間の値を使用します。0 の場合、氷のような感じになります。1 の場合、強い力を加えないとオブジェクトは動きません。

Bounciness

表面にどれだけ弾性があるか。0 の場合は弾性がありません。1 の場合はエネルギーが減ることなく跳ねます。シミュレーションには少量のエネルギーを加えるかもしれませんが、ある程度の近似が予想されます。

FrictionCombine

衝突するオブジェクト間の摩擦をどう処理するか。

– Average

2 つの摩擦力が平均化されます。

– Minimum

2 つの摩擦力のうち小さい方の値が使用されます。

– Maximum

2 つの摩擦力のうち大きい方の値が使用されます。

– Multiply

2 つの摩擦力が互いに乗算されます。

Bounce Combine

衝突するオブジェクト間の跳ね返し度合いをどう処理するか。Friction Combineと同じです。

 ここで期待する珠の動きはビリヤードの玉のような動きになります。跳ね返りがなく、ぶつかっったらぴたりと止まる、そんな設定です。設定は以下のようにしました。

 一方、壁の方は当たったものを反発しない設定にしたいので反発係数を0のして反発しないようにしました。設定は以下になります。

 すると以下のような動きになりました。ビリヤードの珠を並べて突如片方の玉から強烈なインパクトを与えたようなものですから、そら、インパクトを受けた珠はそのままで、受けた先の珠だけ動くのは当たり前でですね。大失敗です。ただ、壁に当たった珠がぴたりと止まったのは想定通りでした。

 この検証から一つ気づけたのは、下の珠にインパクトによる急な力を入れてハイ終わりではなく、継続的に力を入れ続けないといけないということです。実際のそろばんも指でパチンとはじくというよりも珠を指で誘導しますし。

継続的に力を入れる

 動かしたい一番下の珠に継続的に力を入れ続けて、珠を押していく処理をスクリプトに実装します。珠を押し続けるのはUpdate()でAddForce()することで押し続けます。modeは継続的に力を入れ続けたいので、ForceMode.Accelerationを使ってみました。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SorobanScr : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        Vector3 force = new Vector3(0.0f, 10000f, 0.0f);

        this.GetComponent<Rigidbody>().AddForce(
            force,
            ForceMode.Acceleration);
    }

    void OnCollisionEnter(Collision collision)
    {
    }

}

 また、珠と珠がぶつかった時、跳ねてほしくないので、珠の物理マテリアルの反発係数は0にしておきます。これらを合わせて実行すると以下のようになりました。

 微調整の余地はありますが、おおよそ期待通りの動きとなりました。珠4つでも試してみると。

 満足です。ほんと、めちゃくちゃな動きばっかりで泣きそうになってましたが、あきらめなくてよかったです。

まとめ

 まだ、壁に当たった後、ほっておくと少しピクピクなっているので、移動し終わった後に動きを止める制御が必要そうです。ただ、一番下の珠を動かして、その上の珠を押し出し、壁にぶつけて止まる、という物理制御を使って珠を動かせたのが達成できてよかったです。

https://amzn.to/3bd8XOX

コメント