-1
\$\begingroup\$

There a Lerp but also SmoothDamp.

In this script I'm using SmoothDamp but why not using Lerp ? And how should I use this script with the SmoothDamp tp make slowly increasing speed at the start ? Now it's only slow down at the end but I want it also to increase slowly at the start and then slowly down near the end.

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

public class MovementSpeedController : MonoBehaviour
{
    public Transform target;
    private Vector3 velocity = Vector3.zero;
    public float smoothTime = 0.3F;


    void Update()
    {
        transform.position = Vector3.SmoothDamp(transform.position, target.position, ref velocity, smoothTime);
    }
}
\$\endgroup\$
2
  • \$\begingroup\$ If the target is not moving, you can use an easing library, such as gist.github.com/cjddmut/d789b9eb78216998e95c . If the target is moving, you need to write a little bit of logic for acceleration and deceleration. \$\endgroup\$
    – Kevin
    May 13, 2021 at 18:03
  • \$\begingroup\$ Try adding Time.deltaTime at the end \$\endgroup\$
    – John Smith
    May 19, 2021 at 18:53

1 Answer 1

0
\$\begingroup\$

I use the following function to get smooth acceleration/deceleration while moving to the target value/position:

float SmoothTowards(float current, float target, ref float velocity, float accel, float maxVelocity = float.PositiveInfinity)
{
    // The calculations need to be made in positive absolute values,
    // This sing variable is for the case of moving backwards (like from 10 to -5)
    // In the end we'll use this to set values to the original change direction sign:
    int sign = (target - current) > 0 ? 1 : -1;

    float distance = target - current;
    
    // Make the values positive.
    if (velocity < 0) velocity = -velocity;
    if (distance < 0) distance = -distance;

    // d: the distance that is required to decelerate over time and to stop at the target value
    //  with the given aceleration/deceleration and current velocity values:
    float t = velocity / accel;
    float d = velocity * t * 0.5f;
    // remove '* 0.5f' to get the slower deceleration effect. Velocity deceleration will be started earlier and will be slower.

    if (distance <= d)
        velocity -= accel;
    else if (distance - velocity - accel > d)
        velocity += accel;
        
    // Clamp the velocity if needed
    if (velocity > maxVelocity)
        velocity = maxVelocity;
        
    // Set the result to the original change direction sign:
    velocity *= sign;

    // Prevent overshooting:
    if (IsThresholdCrossed(current, current + velocity, target))
        return target;
    else
        return current + velocity;
}

The 'accel' argument is an acceleration/deceleration step. On every call the result will be increased or decreased by this value depending on the 'distance' to the target value. The IsThresholdCrossed(...) function simply checks if the 'target' value is on the other side of the threshold than 'current' value:

bool IsThresholdCrossed(float a, float b, float threshold)
{
    if (a < threshold && threshold <= b ||
        b <= threshold && threshold < a)
            return true;
        else
            return false;
}

How to use it:

float velocityX, velocityY, velocityZ;
float acceleration = 1f;
float maxVelocity = 10f;

void Update()
{
    // First of all, let's get frame rate independent values for acceleration and maxVelocity depending in the last frame time:
    
    // with acceleration =1 the speed will be gradually increased by 1 m/s every second (or decreased while getting closer to the target)
    float accelDelta = acceleration * Time.deltaTime;
    
    // limit max speed for current frame
    float maxVelDelta = maxVelocity * Time.deltaTime;
    
    // Finally, move the transform towards the target:
    transform.position = new Vector3(
        SmoothTowards(transform.position.x, target.position.x, ref velocityX, accelDelta, maxVelDelta),
        SmoothTowards(transform.position.y, target.position.y, ref velocityY, accelDelta, maxVelDelta),
        SmoothTowards(transform.position.z, target.position.z, ref velocityZ, accelDelta, maxVelDelta)
    );
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .