Meiryo’s blog

やってみて詰まったことを備忘録として残すブログ

【Unity】上下に動く床の上のオブジェクトが跳ねるのを軽減させる方法

上下に動くエレベーターのような
動きをする床を作ったのですが
上に乗っているオブジェクトが
跳ね上がったり浮いたりしました。
これを軽減させた話です。

上下に動く床のスクリプト

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

[RequireComponent(typeof(Rigidbody2D))]
public class Elevator : MonoBehaviour
{
    private enum MoveDir
    {
        Up,
        Down,
    }

    [SerializeField]
    private MoveDir _moveDir;

    //移動の速さ
    [SerializeField]
    private float _moveSpeed = 0.0f;
    //移動幅
    [SerializeField]
    private float _moveRange = 1;

    private Rigidbody2D Rb { get; set; }

    private float t { get; set; } = 0.0f;

    //初期位置
    private Vector2 InitPos { get; set; }
    //移動前の位置
    private Vector2 BeforePos { get; set; }
    //移動後の位置
    private Vector2 AfterPos { get; set; }

    void Start()
    {
        Rb = GetComponent<Rigidbody2D>();

        InitPos = transform.position;
        BeforePos = transform.position;

        if (_moveDir == MoveDir.Down)
        {
            _moveRange *= -1;
        }

        AfterPos = transform.position + new Vector3(_moveRange, _moveRange);
    }

    private void FixedUpdate()
    {
        //Rb.MovePosition(new Vector2(InitPos.x, Mathf.Lerp(BeforePos.y, AfterPos.y, t)));
        Rb.MovePosition(new Vector2(InitPos.x, Mathf.SmoothStep(BeforePos.y, AfterPos.y, t)));

        t += _moveSpeed * Time.fixedDeltaTime;

        ChangeMoveInfo();
    }

    private void ChangeMoveInfo()
    {
        if (t > 1.0f)
        {
            var temp = BeforePos;
            BeforePos = AfterPos;
            AfterPos = temp;

            t = 0.0f;
        }
    }
}

オブジェクトの動かし方ですが、
Mathf.Lerpのドキュメント
参考にしています。

使い方

動かしたいオブジェクトに
このスクリプトを貼り、
初動の向きとスピード、
動かしたい範囲を指定して
Rigidbody2DのBodyTypeを
Kinematicにすれば動きます。

動画では
スピードに1、範囲に2を指定しています。

軽減させた方法

MovePotisionの引数に渡す時に
Mathf.Lerpを使っていたのですが
Mathf.SmoothStepに変えました。

LerpとSmoothStepの動きの違いは
ここを見てみてください。

変えた結果がこちら

跳ねや浮きを軽減させることができました。
コメントアウトされているLerpの方を
使うとまた跳ねると思います。

注意

なぜ「跳ねないようにした」
「浮かないようにした」ではなく
「軽減」という表現にしているのかと言うと
スピードを上げたりするとこうなるからです。
このスクリプトでは跳ねたり浮いたりを
完全に防ぐことはできません。

完全に防ぐには
跳ね上がる時と浮く時に
関わっている力を
足したり引いたりすれば
できるかもしれないと思ったのですが
そこまで辿り着けませんでした・・・