Плавно меняйте скорость игрока, когда он покидает зону

#unity3d

Вопрос:

Я пытаюсь сделать special zone расположенное на земле то accelerates the player , при входе в которое скорость игрока увеличивается. Когда он выйдет из этого, то speed smoothly returns to the original . Но теперь, когда игрок покидает зону, то speed instantly becomes the original . Не знаю, как это осознать. Пожалуйста, помогите:)

Мой код:

Игровое движение:

 [SerializeField] private Rigidbody _rigidoby;
    public bool inZone = false;

    private void Update()
    {
        if (inZone == false)
        {
            _rigidoby.velocity = new Vector3(Input.GetAxis("Horizontal") * Time.deltaTime, 0, Input.GetAxis("Vertical") * Time.deltaTime) * 500;
        }
    }
 

Специальная зона:

 private Vector3 _cachedVelocity;
    private Rigidbody _collisionRigidbody;
    [SerializeField] private PlayerMovement _player;

    private void OnTriggerStay(Collider other)
    {
        _player.inZone = true;

        if (_collisionRigidbody == null)
        {
            _collisionRigidbody = other.GetComponent<Rigidbody>();
            _cachedVelocity = _collisionRigidbody.velocity;
        }

        _collisionRigidbody.velocity = new Vector3(Input.GetAxis("Horizontal") * Time.deltaTime, 0, Input.GetAxis("Vertical") * Time.deltaTime) * 1000;
    }

    private void OnTriggerExit(Collider other)
    {
        _collisionRigidbody.velocity = _cachedVelocity;
        _player.inZone = false;
    }
 

Комментарии:

1. Вы ищете формулу для «сглаживания» изменения скорости, вы можете спросить Math SE.

2. @Breakingnotsobad Я искал, что могу использовать Lerp, но не могу придумать, куда его вставить

3. Unity встроила компоненты, которые достигают аналогичных эффектов — они называются эффекторами. Их функциональность относительно ограничена, но вы можете посмотреть, могут ли они вам помочь.

Ответ №1:

Простым решением может быть постепенное снижение скорости обновления после выхода из триггера, как это:

 private void OnTriggerExit(Collider other)
{
    //_collisionRigidbody.velocity = _cachedVelocity;
    _player.inZone = false;
}

private void Update()
{
    if (inZone == false)
    {
        _rigidoby.velocity = new Vector3(Input.GetAxis("Horizontal") * Time.deltaTime, 0, Input.GetAxis("Vertical") * Time.deltaTime) * 500;
    } else {
        If (_collisionRigidbody.velocity > _cachedVelocity;)
        _collisionRigidbody.velocity -= 0.01;
    }
}
 

Другим вариантом может быть запуск сопрограммы при выходе из триггера.

В качестве альтернативы вы можете использовать Vector3.Lerp и установить процент изменения скорости в обновлении следующим образом:

 Vector3 _startingSpeedBeforeDeceleration = Vector3.zero;
private void OnTriggerExit(Collider other)
{
    //_collisionRigidbody.velocity = _cachedVelocity;
    _startingSpeedBeforeDeceleration = _collisionRigidbody.velocity;
    _player.inZone = false;
}

float percent = 0f; //from 0 to 1
private void Update()
{
    if (inZone == false)
    {
        _rigidoby.velocity = new Vector3(Input.GetAxis("Horizontal") * Time.deltaTime, 0, Input.GetAxis("Vertical") * Time.deltaTime) * 500;
    } else {
        If (_collisionRigidbody.velocity > _cachedVelocity;) {
            _collisionRigidbody.velocity = Vector3.Lerp(_startingSpeedBeforeDeceleration, _cachedVelocity, percent);
            percent  = 0,01f;
        }
    }
}
 

Не отлаженный код. Обратите внимание , что я сохранил скорость отправления в переменной _startingSpeedBeforeDeceleration , которая является необязательной и зависит от желаемого поведения движения.
Вы можете поиграть, Vector3.Lerp например , с изменением первого аргумента _startingSpeedBeforeDeceleration в качестве фиксированного значения, и каждый раз, когда скорость тела изменяется таким Vector3.Lerp(_collisionRigidbody.velocity, _cachedVelocity, percent); образом, вы получаете плавное начало и плавный конец, а также изменение максимальной скорости в середине пути. Также percent изменение может быть обработано для настройки поведения движения.