首页 > 代码库 > Unity中的平滑过渡方法了解

Unity中的平滑过渡方法了解

只是刚入门,通过代码以及文档比较一下异同点,以后遇到问题方便选择.

Mathf.Lerp

// UnityEngine.Mathf
/// <summary>
///   <para>Linearly interpolates between a and b by t.</para>
/// </summary>
/// <param name="a">The start value.</param>
/// <param name="b">The end value.</param>
/// <param name="t">The interpolation value between the two floats.</param>
/// <returns>
///   <para>The interpolated float result between the two float values.</para>
/// </returns>
public static float Lerp(float a, float b, float t)
{
	return a + (b - a) * Mathf.Clamp01(t);
}

 

结果是a + (b - a) * Mathf.Clamp01(t),将返回【a,b】之间的数字,参数t表示插值,会在被调用之后由Mathf.Clamp01限制在【0,1】之间

Mathf.LerpUnclamped

// UnityEngine.Mathf
/// <summary>
///   <para>Linearly interpolates between a and b by t with no limit to t.</para>
/// </summary>
/// <param name="a">The start value.</param>
/// <param name="b">The end value.</param>
/// <param name="t">The interpolation between the two floats.</param>
/// <returns>
///   <para>The float value as a result from the linear interpolation.</para>
/// </returns>
public static float LerpUnclamped(float a, float b, float t)
{
	return a + (b - a) * t;
}

 

不限制t的范围,所以返回值不限制在【a,b】之间

Mathf.MoveTowards

 

 

感觉Lerp和MoveTowards基本一样,如果是在update中的匀速运动

经过测试没发现有什么区别.

// UnityEngine.Mathf
/// <summary>
///   <para>Moves a value current towards target.</para>
/// </summary>
/// <param name="current">The current value.</param>
/// <param name="target">The value to move towards.</param>
/// <param name="maxDelta">The maximum change that should be applied to the value.</param>
public static float MoveTowards(float current, float target, float maxDelta)
{
	float result;
	if (Mathf.Abs(target - current) <= maxDelta)
	{
		result = target;
	}
	else
	{
		result = current + Mathf.Sign(target - current) * maxDelta;
	}
	return result;
}

 

   void FixedUpdate()
    {
        t += Time.fixedDeltaTime;
        Debug.Log("<color=red>Lerp is"+Mathf.Lerp(1,5,t)+"</color>");
        current = Mathf.MoveTowards(current, 5, (5-1)*Time.fixedDeltaTime);
        Debug.Log("<color=green>MoveTowards is"+current+"</color>");
    }

 

技术分享

技术分享

http://gamedev.stackexchange.com/questions/49155/lerp-vs-vector-math-one-better-than-the-other

Velocity and lerping are for different purposes. Lerping is great when you know you‘re going to end at the target in a given time; it‘s good for many UI animations, for example.

Use velocity when what you have is the speed of movement and the intent to get to a target at that constant speed. Using the velocity let‘s you smoothly change directions mid-course, slow down or speed up, etc. I had a place I was lerping vectors and changed to steering (velocty/force) because then I could make objects twist and "dodge" each other if they crossed paths.

In general, use lerp for static animations, use velocity (or full physics) for in-game character/object movement.

关于两者区别,摘了一点,主要是Lerp和MoveToward的使用场景可能会有各自的方便之处

Vctor3.Slerp

// UnityEngine.Vector3
/// <summary>
///   <para>Spherically interpolates between two vectors.</para>
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <param name="t"></param>
[ThreadAndSerializationSafe]
public static Vector3 Slerp(Vector3 a, Vector3 b, float t)
{
	Vector3 result;
	Vector3.INTERNAL_CALL_Slerp(ref a, ref b, t, out result);
	return result;
}

 

过渡方向和大小

 
    void Start () {  
            Debug.Log(Vector3.Slerp(Vector3.forward, Vector3.right*2, 0.5f));  
            Debug.Log(new Vector3(0.5f,0,0.5f).normalized*((1+2f)/2));  
        }  

 


具体计算方法应该是先将a,b两个向量单位化,新向量方向,然后计算通过模和取平均值,计算大小


LerpAngle

 
    /// <summary>  
    ///   <para>Same as Lerp but makes sure the values interpolate correctly when they wrap around 360 degrees.</para>  
    /// </summary>  
    /// <param name="a"></param>  
    /// <param name="b"></param>  
    /// <param name="t"></param>  
    public static float LerpAngle(float a, float b, float t)  
    {  
        float num = Mathf.Repeat(b - a, 360f);  
        if (num > 180f)  
        {  
            num -= 360f;  
        }  
        return a + num * Mathf.Clamp01(t);  
    }  

 

注意计算的结果可能为负数或者大于360,需要自行转换

SmoothDamp


 
    // UnityEngine.Mathf  
    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;  
    }  

 


http://devblog.aliasinggames.com/smoothdamp

http://devblog.aliasinggames.com/how-to-lerp-properly/

http://devblog.aliasinggames.com/lerp-in-unity/

这里有篇关于SmoothDamp的文章,抽空再仔细拜读.

Unity中的平滑过渡方法了解