Vector3.SmoothDamp 平滑阻尼

Vector3.SmoothDamp 平滑阻尼
static function SmoothDamp (current : Vector3, target : Vector3, ref currentVelocity : Vector3, smoothTime : float, maxSpeed : float = Mathf.Infinity, deltaTime : float = Time.deltaTime) : Vector3

Parameters参数
current
The current position.
当前的位置
target
The position we are trying to reach.
我们试图接近的位置
currentVelocity
The current velocity, this value is modified by the function every time you call it.
当前速度,这个值由你每次调用这个函数时被修改
smoothTime
Approximately the time it will take to reach the target. A smaller value will reach the target faster.
到达目标的大约时间,较小的值将快速到达目标
maxSpeed
Optionally allows you to clamp the maximum speed.
选择允许你限制的最大速度
deltaTime
The time since the last call to this function. By default Time.deltaTime. 
自上次调用这个函数的时间。默认为 Time.deltaTime
Description描述

Gradually changes a vector towards a desired goal over time.

随着时间的推移,逐渐改变一个向量朝向预期的目标。

The vector is smoothed by some spring-damper like function, which will never overshoot. The most common use is for smoothing a follow camera.

向量由一些像弹簧阻尼器函数平滑,这将永远不会超过。最常见的用途是平滑跟随相机。

C#JavaScript
// Smooth towards the target
//平滑朝向目标
var target : Transform;
var smoothTime = 0.3;
private var velocity = Vector3.zero;

function Update () {
    // Define a target position above and behind the target transform
    //定义一个目标位置在目标变换的上方并且在后面
    var targetPosition : Vector3 = target.TransformPoint(Vector3(0, 5, -10));

    // Smoothly move the camera towards that target position
    //平滑地移动摄像机朝向目标位置
    transform.position = Vector3.SmoothDamp(transform.position, targetPosition,
    velocity, smoothTime);
}

http://www.vfkjsd.cn/unity/Script/Vector3/Vector3.SmoothDamp.html

二、

SmoothDamp函数

SmoothDamp函数在使用过程中比较容易出现的一个问题就是容易在代码较复杂的情形下将currentVelocity这个参数需要的变量定义为局部变量,如下:

 public float smoothTime = 0.3F;
 
 void Update()
 {
         Vector3 velocity = Vector3.zero;
         transform.position = Vector3.SmoothDamp(transform.position, target, ref velocity, smoothTime);
     }
 }
使用局部变量的效果如下图所示,越来越慢,定义的平滑时间明明是0.3f,怎么用了10几秒的时间都还在缓慢移动?
image

为了便于理解,我们来看一下Mathf.SmoothDamp的具体实现:

public static float SmoothDamp(float current, float target, ref float currentVelocity, float smoothTime, [DefaultValue("Mathf.Infinity")] float maxSpeed, [DefaultValue("Time.deltaTime")] float deltaTime)
        {
            smoothTime = Mathf.Max(0.0001f, smoothTime);
            float num = 2f / smoothTime;
            float num2 = num * deltaTime;
            float num3 = 1f / (1f + num2 + 0.48f * num2 * num2 + 0.235f * num2 * num2 * num2);
            float num4 = current - target;
            float num5 = target;
            float num6 = maxSpeed * smoothTime;
            num4 = Mathf.Clamp(num4, -num6, num6);
            target = current - num4;
            float num7 = (currentVelocity + num * num4) * deltaTime;
            currentVelocity = (currentVelocity - num * num7) * num3;
            float num8 = target + (num4 + num7) * num3;
            if (num5 - current > 0f == num8 > num5)
            {
                num8 = num5;
                currentVelocity = (num8 - num5) / deltaTime;
            }
            return num8;
        }
通过具体的实现我们就可以很清楚的发现,currentVelocity这个变量是先使用,然后再赋值,通过ref传递就是为了获取到上一次计算得到的速度值,如果我们使用局部变量,每一次速度都是零,相当于刚开始进行平滑移动,平滑的距离(transform.position到target)不断在缩短,然而平滑时间却没有变化,为了保证大约在平滑的时间内完成平滑移动,这个起步速度肯定是越来越慢的,所以就导致了上图中的问题。
我们把currentVelocity改为全局变量,就可以看到正常效果了

private Vector3 target = new Vector3(0, 0, 5);
    public float smoothTime = 0.3F;
    private Vector3 velocity = Vector3.zero;
    void Update()
    {
            transform.position = Vector3.SmoothDamp(transform.position, target, ref velocity, smoothTime);
    }
效果如下:


image

作者:简D_EVELOPER
链接:https://www.jianshu.com/p/8a5341c6d5a6
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

https://www.jianshu.com/p/8a5341c6d5a6

posted on 2020-08-18 10:59  ZhYQ_note  阅读(2382)  评论(0)    收藏  举报

导航