Unity【Lerp & Slerp】- 线性插值与球形插值的区别

简介: Unity【Lerp & Slerp】- 线性插值与球形插值的区别

在Unity的向量Vector和四元数Quaternion类中,均包含线性插值Lerp和球形插值Slerp的函数,那么两者之间有何区别,通过下面的例子进行观察:

image.gif


image.gif


图一中黄色线红色线相交的点是从点A到点B进行线性插值得出的结果,图二则是球形插值得出的结果,或许称之为弧形插值更容易理解。二者的区别从图中可以明显看出,从四元数的角度来看,线性插值每帧得出的旋转结果是不均匀的,从代数的角度思考,如果两个单位四元数之间进行插值,如图一中的线性插值,得到的四元数并不是单位四元数,因此球形插值更为合理,因为它是不改变长度的。

测试代码如下:

usingUnityEngine;
usingUnityEditor;
/// <summary>/// 线性插值/// </summary>publicclassLerpExample : MonoBehaviour{
    [SerializeField] privateTransforma; //点A    [SerializeField] privateTransformb; //点BprivatevoidOnDrawGizmos()
    {
Handles.Label(transform.position, "O");
Handles.Label(a.position, "A");
Handles.Label(b.position, "B");
Handles.color=Color.cyan;
//以transform.position作为点O//绘制OA线段Handles.DrawLine(transform.position, a.position);
//绘制OB线段Handles.DrawLine(transform.position, b.position);
for (inti=1; i<10; i++)
        {
//插值点Vector3l=Vector3.Lerp(a.position, b.position, i* .1f);
Handles.color=Color.red;
//绘制点O到插值点的线段Handles.DrawLine(transform.position, l);
Handles.color=Color.yellow;
//绘制插值点之间的线段Handles.DrawLine(l, Vector3.Lerp(a.position, b.position, (i-1) * .1f));
Handles.Label(l, $"线性插值{i}");
        }
Handles.DrawLine(b.position, Vector3.Lerp(a.position, b.position, .9f));
    }
}

image.gif

usingUnityEngine;
usingUnityEditor;
/// <summary>/// 球形插值/// </summary>publicclassSlerpExample : MonoBehaviour{
    [SerializeField] privateTransforma; //点A    [SerializeField] privateTransformb; //点BprivatevoidOnDrawGizmos()
    {
Handles.Label(transform.position, "O");
Handles.Label(a.position, "A");
Handles.Label(b.position, "B");
Handles.color=Color.cyan;
//以transform.position作为点O//绘制OA线段Handles.DrawLine(transform.position, a.position);
//绘制OB线段Handles.DrawLine(transform.position, b.position);
for (inti=1; i<10; i++)
        {
//插值点Vector3l=Vector3.Slerp(a.position, b.position, i* .1f);
Handles.color=Color.red;
//绘制点O到插值点的线段Handles.DrawLine(transform.position, l);
Handles.color=Color.yellow;
//绘制插值点之间的线段Handles.DrawLine(l, Vector3.Slerp(a.position, b.position, (i-1) * .1f));
Handles.Label(l, $"球形插值{i}");
        }
Handles.DrawLine(b.position, Vector3.Slerp(a.position, b.position, .9f));
    }
}

image.gif

在对Transform组件中的Position坐标和Rotation旋转进行插值运算时, 通常用Vector3中的插值函数去处理Position,用Quaternion中的插值函数去处理Rotation。

如果我们使用Vector3中的插值函数去处理Rotation,则会出现如下这种情况:

image.gif

代码如下:

usingUnityEngine;
usingSystem.Collections;
publicclassExample : MonoBehaviour{
    [SerializeField] privateTransformpoint1;
    [SerializeField] privateTransformpoint2;
privateIEnumeratorExampleCoroutine(Transformtarget)
    {
floatbeginTime=Time.time;
Vector3beginPosition=transform.position;
Vector3beginRotation=transform.eulerAngles;
for (varduration=2f; (Time.time-beginTime) <duration;)
        {
floatt= (Time.time-beginTime) /duration;
transform.position=Vector3.Lerp(beginPosition, target.position, t);
transform.eulerAngles=Vector3.Lerp(beginRotation, target.eulerAngles, t);
yieldreturnnull;
        }
transform.position=target.position;
transform.eulerAngles=target.rotation.eulerAngles;
    }
privatevoidOnGUI()
    {
if (GUILayout.Button("POINT1", GUILayout.Width(200f), GUILayout.Height(50f)))
        {
StartCoroutine(ExampleCoroutine(point1));
        }
if (GUILayout.Button("POINT2", GUILayout.Width(200f), GUILayout.Height(50f)))
        {
StartCoroutine(ExampleCoroutine(point2));
        }
    }
}

image.gif

下面是使用Quaternion.Lerp得出的结果:

image.gif

代码如下:

usingUnityEngine;
usingSystem.Collections;
publicclassExample : MonoBehaviour{
    [SerializeField] privateTransformpoint1;
    [SerializeField] privateTransformpoint2;
privateIEnumeratorExampleCoroutine(Transformtarget)
    {
floatbeginTime=Time.time;
Vector3beginPosition=transform.position;
QuaternionbeginRotation=transform.rotation;
for (varduration=2f; (Time.time-beginTime) <duration;)
        {
floatt= (Time.time-beginTime) /duration;
transform.position=Vector3.Lerp(beginPosition, target.position, t);
transform.rotation=Quaternion.Lerp(beginRotation, target.rotation, t);
yieldreturnnull;
        }
transform.position=target.position;
transform.rotation=target.rotation;
    }
privatevoidOnGUI()
    {
if (GUILayout.Button("POINT1", GUILayout.Width(200f), GUILayout.Height(50f)))
        {
StartCoroutine(ExampleCoroutine(point1));
        }
if (GUILayout.Button("POINT2", GUILayout.Width(200f), GUILayout.Height(50f)))
        {
StartCoroutine(ExampleCoroutine(point2));
        }
    }
}

image.gif

目录
相关文章
|
API 图形学
【Unity细节】RigidBody中Dynamic和Kinematic的区别
【Unity细节】RigidBody中Dynamic和Kinematic的区别
153 0
|
图形学
【unity细节】unity物体Model和prefab的区别
【unity细节】unity物体Model和prefab的区别
212 0
|
vr&ar 图形学
【100个 Unity小知识点】 | Unity两种获取游戏对象的方法,GameObject.Find 和 Transform.Find区别
Unity 小科普 老规矩,先介绍一下 Unity 的科普小知识: Unity是 实时3D互动内容创作和运营平台 。 包括游戏开发、美术、建筑、汽车设计、影视在内的所有创作者,借助 Unity 将创意变成现实。 Unity 平台提供一整套完善的软件解决方案,可用于创作、运营和变现任何实时互动的2D和3D内容,支持平台包括手机、平板电脑、PC、游戏主机、增强现实和虚拟现实设备。 也可以简单把 Unity 理解为一个游戏引擎,可以用来专业制作游戏!
【100个 Unity小知识点】 | Unity两种获取游戏对象的方法,GameObject.Find 和 Transform.Find区别
|
vr&ar 图形学
【100个 Unity小知识点】☀️ | Unity 中的原始预制体 和 预制体变体 的区别和作用
Unity 小科普 老规矩,先介绍一下 Unity 的科普小知识: Unity是 实时3D互动内容创作和运营平台 。 包括游戏开发、美术、建筑、汽车设计、影视在内的所有创作者,借助 Unity 将创意变成现实。 Unity 平台提供一整套完善的软件解决方案,可用于创作、运营和变现任何实时互动的2D和3D内容,支持平台包括手机、平板电脑、PC、游戏主机、增强现实和虚拟现实设备。 也可以简单把 Unity 理解为一个游戏引擎,可以用来专业制作游戏!
【100个 Unity小知识点】☀️ | Unity 中的原始预制体 和 预制体变体 的区别和作用
|
vr&ar 图形学
【Unity3D 灵巧小知识点】 | Unity中 OnEnable 和 Awake、Start 的区别
Unity 小科普 老规矩,先介绍一下 Unity 的科普小知识: Unity是 实时3D互动内容创作和运营平台 。 包括游戏开发、r美术、建筑、汽车设计、影视在内的所有创作者,借助 Unity 将创意变成现实。 Unity 平台提供一整套完善的软件解决方案,可用于创作、运营和变现任何实时互动的2D和3D内容,支持平台包括手机、平板电脑、PC、游戏主机、增强现实和虚拟现实设备。
|
图形学
Unity查找物体的四大主流方法及区别
Unity查找物体的四大主流方法及区别GameObject.Find()Transform.Find()GameObject.FindGameObjectsWithTag()FindObjectsOfType() 不少新人在刚接触unity查找物体的方法时,因为没有认识到几种查找物体方法它们之间的区别,而遇到bug 即“空引用异常”报错,我在这里说明一下它们的区别,供大家参考。
1920 0
|
图形学
unity3d 的Quaternion.identity和transform.rotation区别是什么
Quaternion.identity就是指Quaternion(0,0,0,0),就是每旋转前的初始角度,是一个确切的值,而transform.rotation是指本物体的角度,值是不确定的,比如可以这么设置transform.
|
图形学
UNITY3D单词学习 speed和velocity的区别
在日常用语中,这两个词没有区别,可以通用. 而在物理学里,velocity 是一个矢量(vector quantity)表示起点与终点间直线距离的长度除以所用时间所得的量,并注明方向;而 speed 是一个数量(scalar quantity),是指起点到终点所走过的所有路程除以所用时间所得的量,且不标明方向.