unity vector3.slerpslerp 怎么理解

vector3.slerp的逻辑是?_unity3d吧_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:55,498贴子:
vector3.slerp的逻辑是?收藏
学unity3d?10余年教学案例精髓,选择完美动力unity3d国际培训中心
踢出漂亮的弧线球....
路径是弧线
这是我在蛮牛的回答
根据我的测试,这个东西应该是返回2个向量角度与长度变化的插值向量。API里写的例子有点晦涩,我是这么理解的, center -= new Vector3(0, 1, 0);没什么特殊含义,就是做出2个不同大小角度的向量。Vector3 riseRelCenter = sunrise.position -
Vector3 setRelCenter = sunset.position -将起点与终点相对于center点移到世界坐标系原点计算。 transform.position +=将计算出的位置还原。取几个特殊值就能明白这个方法,取插值0.5得出的向量方向是初始2个向量的平分线方向,其大小等于初始2个向量的平均值。
登录百度帐号推荐应用
为兴趣而生,贴吧更懂你。或Unity3D - 详解Quaternion类(二) - 推酷
Unity3D - 详解Quaternion类(二)
四、Quaternion类静态方法
Quaternion中的静态方法有9个即:Angle方法、Dot方法、Euler方法、FromToRotation方法、Inverse方法、Lerp方法、LookRotation方法、RotateToWards方法和Slerp方法。关于静态的方法的使用就是直接用类名调用其静态方法,例如Quaternion.Angle(q1,q2);下面对这些静态方法做下分析。
1、Angle方法
1.1 函数原型
public static float Angle(Quaternion a,Quaternion b);
该方法可以计算两个旋转状态a达到b时需要旋转的最小夹角。
1.2 实例演示
using UnityE
using System.C
public class Angle_ts : MonoBehaviour {
// Use this for initialization
void Start () {
Quaternion q1 = Quaternion.
Quaternion q2 = Quaternion.
q1.eulerAngles = new Vector3(30.0f, 40.0f, 50.0f);
float a1 = Quaternion.Angle(q1, q2);
float a2 = 0.0f;
Vector3 v = Vector3.
q1.ToAngleAxis(out a2,out v);
Debug.Log(&a1: & + a1);
Debug.Log(&a2: & + a2);
Debug.Log(&q1的欧拉角: & + q1.eulerAngles + & q1的rotation: & + q1);
Debug.Log(&q2的欧拉角: & + q2.eulerAngles + & q2的rotation: & + q2);
// Update is called once per frame
void Update () {
从输出结果可以看出a1和a2的值相等,即Angle的返回值是两个Quaternion实例转换的最小夹角。
2、Dot方法-点乘
2.1 函数原型
public static float Dot(Quaternion a,Quaternion b);
该方法可以根据点乘的结果,判断a和b对应欧拉角的关系。
例如有两个Quaternion实例q1(x1,y1,z1,w1)和q2(x2,y2,z2,w2),则float f = Quaternion.Dot(q1,q2);即f = x1*x2+y1*y2+z1*z2+w1*w2,结果值f的范围为[-1,1]。
当f=+(-)1时,q1和q2对应的欧拉角是相等的,即旋转状态是一致的。特别地,当f = -1时,说明其中一个rotation比另外一个rotation多旋转了360&。
2.2 实例演示
using UnityE
using System.C
public class Dot_ts : MonoBehaviour {
public Transform A, B;
Quaternion q1 = Quaternion.
Quaternion q2 = Quaternion.
// Use this for initialization
void Start () {
A.eulerAngles = new Vector3(0.0f, 40.0f, 0.0f);
B.eulerAngles = new Vector3(0.0f, 360.0f + 40.0f, 0.0f);
float f = Quaternion.Dot(q1, q2);
Debug.Log(&q1的欧拉角: & + q1.eulerAngles + & q1的rotation: & + q1);
Debug.Log(&q2的欧拉角: & + q2.eulerAngles + & q2的rotation: & + q2);
Debug.Log(&Dot(q1,q2): & + f);
// Update is called once per frame
void Update () {
从输出结果可以证明q1和q2的欧拉角相等,但是rotation值却是相反的,也说明当Dot的返回值为-1时,两个参数的角度相差360&。
3、Euler方法
3.1 函数原型
public static Quaternion Euler(Vector3 euler);
public static Quaternion Euler(float x,float y,float z);
该方法用于返回欧拉角Vector3(ex,ey,ez)对应的四元数Quaternion q(qx,qy,qz,qw)。其对应关系如下:
已知PIover180 = 3. = 0.f是计算机图形学中的一个常亮,其变换过程如下:
ex = ex * PIover180 / 2.0f;
ey = ey * PIover180 / 2.0f;
ez = ez * PIover180 / 2.0f;
qx = Mathf.Sin(ex) * Mathf.Cos(ey) * Mathf.Cos(ez) + Mathf.Cos(ex) * Mathf.Sin(ey) * Mathf.Sin(ez);
qy = Mathf.Cos(ex) * Mathf.Sin(ey) * Mathf.Cos(ez) - Mathf.Sin(ex) * Mathf.Cos(ey) * Mathf.Sin(ez);
qz = Mathf.Cos(ex) * Mathf.Cos(ey) * Mathf.Sin(ez) - Mathf.Sin(ex) * Mathf.Sin(ey) * Mathf.Cos(ez);
qw = Mathf.Cos(ex) * Mathf.Cos(ey) * Mathf.Cos(ez) + Mathf.Sin(ex) * Mathf.Sin(ey) * Mathf.Sin(ez);
3.2 验证变换过程
using UnityE
using System.C
public class Euler_ts : MonoBehaviour {
public float ex, ey,
float qx, qy, qz,
float PIover180 = 0.f;
Quaternion q = Quaternion.
void OnGUI()
if(GUI.Button(new Rect(10.0f,10.0f,100.0f,45.0f),&计算&))
euler = new Vector3(ex,ey,ez);
Debug.Log(&欧拉角Euler(ex,ey,ez): & + euler);
q = Quaternion.Euler(ex, ey, ez);
Debug.Log(&对应的四元数为: & + q);
Debug.Log(&q.x: & + q.x + & q.y: & + q.y + & q.z: & + q.z + & q.w: & + q.w);
//验证算法
ex = ex * PIover180 / 2.0f;
ey = ey * PIover180 / 2.0f;
ez = ez * PIover180 / 2.0f;
qx = Mathf.Sin(ex) * Mathf.Cos(ey) * Mathf.Cos(ez) + Mathf.Cos(ex) * Mathf.Sin(ey) * Mathf.Sin(ez);
qy = Mathf.Cos(ex) * Mathf.Sin(ey) * Mathf.Cos(ez) - Mathf.Sin(ex) * Mathf.Cos(ey) * Mathf.Sin(ez);
qz = Mathf.Cos(ex) * Mathf.Cos(ey) * Mathf.Sin(ez) - Mathf.Sin(ex) * Mathf.Sin(ey) * Mathf.Cos(ez);
qw = Mathf.Cos(ex) * Mathf.Cos(ey) * Mathf.Cos(ez) + Mathf.Sin(ex) * Mathf.Sin(ey) * Mathf.Sin(ez);
Debug.Log(&qx: & + qx + & qy: & + qy + & qz: & + qz + & qw: & + qw);
从输出结果可以证明该公式是正确,另外转换后的四元数直接输出的话,如下:
q = Quaternion.Euler(ex, ey, ez);
Debug.Log(&对应的四元数为: & + q);
输出值是做了四舍五入处理的。
4、FromToRotation方法
public static Quaternion FromToRotation(Vector3 fromDirection,Vector3 ToDirection);
在前面介绍了SetFromToRotation实例方法,它们的功能都是一样的只不过用法稍有不同。使用FromToRotation类静态方法,需要直接使用类名进行调用,如Quaternion.FromToRotation(v1,v2);
在此就不做演示了!
5、Inverse方法
5.1 函数原型
public static Quaternion Inverse(Quaternion rotation);
该方法可以返回参数rotation的逆向Quaternion值。
例如rotation(x,y,z,w),那么Quaternion.Inverse(rotation) = (-x,-y,-z,w)。假设rotation的欧拉角为(a,b,c),则transform.rotation = Quaternion.Inverse(rotation)相当于transform依次绕自身坐标系的z轴、x轴和y轴分别旋转-c&、-a&和-z&。由于是在局部坐标系内的变换,最后transform的欧拉角的各个分量值并不一定等于-a、-b或-c。
5.2 实例演示
using UnityE
using System.C
public class Invers_ts : MonoBehaviour {
public Transform A, B;
// Use this for initialization
void Start () {
Quaternion q1 = Quaternion.
Quaternion q2 = Quaternion.
q1.eulerAngles = new Vector3(30.0f,40.0f,50.0f);
q2 = Quaternion.Inverse(q1);
A.rotation = q1;
B.rotation = q2;
Debug.Log(&q1的欧拉角: & + q1.eulerAngles + &q1的rotation: & + q1);
Debug.Log(&q2的欧拉角: & + q2.eulerAngles + &q2的rotation: & + q2);
// Update is called once per frame
void Update () {
6、Lerp和Slerp方法
6.1 函数原型
public static Quaternion Lerp(Quaternion form, Quaternion to,float t);
public static Quaternion Slerp(Quaternion form, Quaternion to,float t);
两种方法的作用都是返回从form到to的插值。当参数t&=0时返回值为from,当参数t&=1时返回值为to。其中Lerp是线性差值,而Slerp是球面插值。
6.2 实例演示
using UnityE
using System.C
public class LerpAndSlerp_ts : MonoBehaviour
public Transform A, B, C,D;
float speed = 0.2f;
float total = 0.0f;
// Use this for initialization
void Start () {
// Update is called once per frame
void Update () {
total += Time.deltaTime *
if(total &= 1.0f)
total = 1.0f;
C.rotation = Quaternion.Lerp(A.rotation, B.rotation, total);
D.rotation = Quaternion.Lerp(A.rotation, B.rotation, total);
//C.rotation = Quaternion.Lerp(A.rotation, B.rotation, Time.deltaTime * speed);
//D.rotation = Quaternion.Lerp(A.rotation, B.rotation, Time.deltaTime * speed);
7、RotateTowards方法
7.1 函数原型
public static Quaternion RotateTowards(Quaternion from, Quaternion to, float maxDegreesDelta);
该方法也是一个插值方法,即从返回参数from到to的插值,且返回值的最大角度不超过maxDegreesDelta。maxDegreesDelta是角度值,不是插值系数,当maxDegreesDelta & 0时,将进行逆向插值即从to到from的方向进行插值计算。
7.2 实例演示
using UnityE
using System.C
public class RotateToWards_ts : MonoBehaviour {
public Transform A, B, C;
float speed = 10.0f;
float total = 0.0f;
// Use this for initialization
void Start()
// Update is called once per frame
void Update()
total += Time.deltaTime *
if (total &= 1.0f)
total = 1.0f;
C.rotation = Quaternion.RotateTowards(A.rotation, B.rotation, Time.time * speed - 40.0f);
Debug.Log(&C与A的欧拉角的插值: & + (C.eulerAngles - A.eulerAngles) + &maxDegreesDelta: & + (Time.time * speed - 40.0f));
8、LookRotation方法
public static Quaternion LookRotation(Vector3 forward);
public static Quaternion LookRotation(Vector3 forward,Vector3 upwards);
参数forward为返回Quaternion实例的forward朝向。该方法和前面讲到的SetLookRotation实例方法的功能是一样的,故不多做阐述了。
五、Quaternion类运算符
Quaternion类涉及到两个Quaternion对象相乘和Quaternion对象与Vector3对象相乘,那么就必须重载&*&运算符。
1、函数原型
public static Quaternion operator *(Quaternion lhs, Quaternion rhs);
public static Vector3 operator *(Quaternion rotation, Vector3 point);
2、两个Quaternion对象相乘
对于两个Quaternion对象相乘主要用于自身旋转变换,例如:
B.rotation *= A.
B会绕着B的局部坐标系的z、x、y轴按照先绕z轴再绕x轴最后绕y轴的旋转次序,分别旋转A.eulerAngles.z度、A.eulerAngles.x度、和A.eulerAngles.y度。由于是绕着局部坐标系进行旋转,所以当绕着其中一个轴进行旋转时,可能会影响其余两个坐标轴方向的欧拉角(除非其余两轴的欧拉角都为0才不会受到影响)。
假如A的欧拉角为aEuler(ax,ay,az),则沿着B的初始局部坐标系的aEuler方向向下看B在绕着aEuler顺时针旋转。B的旋转状况还受到其初始状态的影响。
2.1 实例演示
using UnityE
using System.C
public class Multiply1_ts : MonoBehaviour {
public Transform A, B;
// Use this for initialization
void Start () {
A.eulerAngles = new Vector3(1.0f, 1.5f, 2.0f);
// Update is called once per frame
void Update () {
B.rotation *= A.
Debug.Log(B.eulerAngles);
B绕着其自身坐标系的Vector3(1.0f,1.5f,2.0f)方向旋转。虽然每次都绕着这个轴向旋转的角度相同,但角度的旋转在3个坐标轴的值都不为零,三个轴的旋转会相互影响,所以B的欧拉角的各个分量的每次递增是不固定的。
3、Quaternion对象与Vector3对象
对于Quaternion对象与Vector3对象相乘主要用于自身移动变换,例如
transform.position += tansform.rotation * A;
其中A为Vector3的对象。transform对应的对象会沿着自身坐标系中向量A的方向移动A的模长的距离。transform.rotation与A相乘可以确定移动的方向和距离。
3.1 实例演示
using UnityE
using System.C
public class Multiply2_ts : MonoBehaviour {
public Transform A;
float speed = 0.1f;
// Use this for initialization
void Start () {
A.position = Vector3.
A.eulerAngles = new Vector3(0.0f, 45.0f, 0.0f);
// Update is called once per frame
void Update () {
A.position += A.rotation * (Vector3.forward * speed);
Debug.Log(A.position);
4、两个Quaternion对象相乘与Quaternion对象与Vector3对象相乘的异同
设A为两个两个Quaternion对象相乘的结果。B为Quaternion对象与Vector3对象相乘的结果。其中A为Quaternion类型,B为Vector3类型。
A与B的相同之处是它们都通过自身坐标系的“相乘”方式来实现在世界坐标系中的变换。
A主要用来实现transform绕自身坐标系的某个轴旋转,B主要用来实现transform沿着自身坐标系的某个方向移动。
必须遵守Quaternion对象*Vector3对象的形式,不可以颠倒顺序。
由于它们都是相对于自身坐标系进行的旋转或移动,所以当自身坐标系的轴向和世界坐标系的轴向不一致时,它们绕着自身坐标系中的某个轴向的变动都会影响到物体在世界坐标系中各个坐标轴的变动。
--------------------------------------------------------------------------------------------------------至此完结!-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致今天准备学习和研究下unity3d的四元数 Quaternion
四元数在电脑图形学中用于表示物体的旋转,在unity中由x,y,z,w 表示四个值。
四元数是最简单的超复数。 复数是由实数加上元素 i 组成,其中i^2 = -1 ,。 相似地,四元数都是由实数加上三个元素 i、j、k 组成,而且它们有如下的关系: i^2 = j^2 = k^2 = ijk = -1 , 每个四元数都是 1、i、j 和 k 的线性组合,即是四元数一般可表示为a + bi + cj + dk ,。
具体的四元数知识可从百度、维基等网站了解。
/view/319754.htm
现在只说说在unity3D中如何使用Quaternion来表达物体的旋转。
基本的旋转我们可以用脚本内置旋转函数transform.Rotate()来实现。
function Rotate (eulerAngles : Vector3, relativeTo : Space = Space.Self) : void
但是当我们希望对旋转角度进行一些计算的时候,就要用到四元数Quaternion了。我对高等数学来说就菜鸟一个,只能用最朴素的方法看效果了。
Quaternion的变量比较少也没什么可说的,大家一看都明白。唯一要说的就是xyzw的取值范围是[-1,1],物体并不是旋转一周就所有数值回归初始值,而是两周。
初始值: (0,0,0,1)
沿着y轴旋转:180&(0,1,0,0) 360&(0,0,0,-1)540&(0,-1,0,0) 720&(0,0,0,1)
沿着x轴旋转:180&(-1,0,0,0) 360&(0,0,0,-1)540&(1,0,0,0) 720&(0,0,0,1)
无旋转的写法是Quaternion.identify
现在开始研究Quaternion的函数都有什么用。
1)function ToAngleAxis (out angle : float, out axis : Vector3) : void
Description
Converts a rotation to angle-axis representation
这个函数的作用就是返回物体的旋转角度(物体的z轴和世界坐标z轴的夹角)和三维旋转轴的向量到变量out angle 和out axis
var a=0.0;
var b=Vector3.
transform.rotation.ToAngleAxis(a,b);
输入:transform.localEularAngles=(0,0,0);
输出: a=0, b=(1,0,0);
输入:transform.localEularAngles=(0,90,0);
输出:a=90, b=(0,1,0);
输入:transform.localEularAngles=(270,0,0);
输出:a=90, b=(-1,0,0)
2)function SetFromToRotation (fromDirection : Vector3, toDirection : Vector3) : void
Description
Creates a rotation which rotates from fromDirection to toDirection.
这个函数的作用是把物体的fromDirection旋转到toDirection
var a:Vector3;
var b:Vector3;
var headUpDir:Vector3;
q.SetFromToRotation(a,b);
transform.rotation=q;
headUpDir=transform.TransformDirection(Vector3.Forward);
输入:a=Vector3(0,0,1); b=Vector3(0,1,0)//把z轴朝向y轴
输出: q=(-0.7,0,0,0.7); headUpDir=(0,1,0)
输入:a=Vector3(0,0,1); b=Vector3(1,0,0)//把z轴朝向x轴
输出: q=(0,0.7,0,0.7); headUpDir=(1,0,0)
输入:a=Vector3(0,1,0); b=Vector3(1,0,0)//把y轴朝向x轴
输出: q=(0,0,-0.7,0.7); headUpDir=(0,0,1)
3)function SetLookRotation (view : Vector3, up : Vector3 = Vector3.up) : void
Description
Creates a rotation that looks along forward with the the head upwards along upwards
Logs an error if the forward direction is zero.
这个函数建立一个旋转使z轴朝向view y轴朝向up。这个功能让我想起了Maya里的一种摄像机lol,大家自己玩好了,很有趣。
var obj1: T
var obj2: T
q.SetLookRotation(obj1.position, obj2.position);
transform.rotation=q;
然后大家拖动obj1和obj2就可以看到物体永远保持z轴朝向obj1, 并且以obj2的位置来保持y轴的倾斜度。
傻逗我玩了半天 哈哈^^ 这个功能挺实用的。
4)function ToString () : string
Description
Returns a nicely formatted string of the Quaternion
这个一般用不着吧?看不懂的一边查字典去~
Class Functions
1)四元数乘法 *
建议非特别了解的人群就不要用了。
作用很简单,c=a*b (c,a,b&Quaternion)可以理解为 &c=&a+&b
但是a*b 和b*a效果不一样的。
2) == 和 !=
3)static function Dot (a : Quaternion, b : Quaternion) : float
Description
The dot product between two rotations
点积,返回一个float. 感觉用处不大。Vector3.Angle()比较常用。
4)static function AngleAxis (angle : float, axis : Vector3) : Quaternion
Description
Creates a rotation which rotates angle degrees around axis.
物体沿指定轴向axis旋转角度angle, 很实用的一个函数也是。
var obj1: T
var obj2: T
//物体沿obj2的z轴旋转,角度等于obj1的z轴。
q=Quaternion.AngleAxis(obj1.localEularAngle.z, obj2.TransformDirection(Vector3.forward));
transform.rotation=q;
5)static function FromToRotation (fromDirection : Vector3, toDirection : Vector3) : Quaternion
Description
Creates a rotation which rotates from fromDirection to toDirection.
Usually you use this to rotate a transform so that one of its axes eg. the y-axis & follows a target direction toDirection in world space.
跟SetFromToRotation差不多,区别是可以返回一个Quaternion。通常用来让transform的一个轴向(例如 y轴)与toDirection在世界坐标中同步。
6)static function LookRotation (forward : Vector3, upwards : Vector3 = Vector3.up) : Quaternion
Description
Creates a rotation that looks along forward with the the head upwards along upwards
Logs an error if the forward direction is zero.
跟SetLootRotation差不多,区别是可以返回一个Quaternion。
7)static function Slerp (from : Quaternion, to : Quaternion, t : float) : Quaternion
Description
Spherically interpolates from towards to by t.
从from 转换到to,移动距离为t。 也是很常用的一个函数,用法比较多,个人感觉比较难控制。当两个quaternion接近时,转换的速度会比较慢。
var obj1: T
var t=0.1;
//让物体旋转到与obj1相同的方向
q=Quaternion.Slerp(transform.rotation, obj1.rotation,t);
transform.rotation=q;
根据我个人推测,可能t 代表的是from 和to 之间距离的比例。 为此我做了实验并证明了这一点即:
q=Quaternion.Slerp(a,b,t);
q,a,b&Quaternion
q=a+(b-a)*t
并且t最大有效范围为0~1
var obj1: T
var obj2:Transform;
var t=0.1;
//让物体obj1和obj2 朝向不同的方向,然后改变t
q=Quaternion.Slerp(obj1.rotation, obj2.rotation,t);
transform.rotation=q;
t+=Input.GetAxis(&horizontal&)*0.1*Time.deltaTime;
7)static function Lerp (a : Quaternion, b : Quaternion, t : float) : Quaternion
Description
Interpolates from towards to by t and normalizes the result afterwards.
This is faster than Slerp but looks worse if the rotations are far apart
跟Slerp相似,且比Slerp快,.但是如果旋转角度相距很远则会看起来很差。
8)static function Inverse (rotation : Quaternion) : Quaternion
Description
Returns the Inverse of rotation.
返回与rotation相反的方向
9)static function Angle (a : Quaternion, b : Quaternion) : float
Description
Returns the angle in degrees between two rotations a and b.
计算两个旋转之间的夹角。跟Vector3.Angle() 作用一样。
10)static function Euler (x : float, y : float, z : float) : Quaternion
Description
Returns a rotation that rotates z degrees around the z axis, x degrees around the x axis, and y degrees around the y axis (in that order).
把旋转角度变成对应的Quaternion
以上就是Quaternion的所有函数了。
关于应用,就说一个,其他的有需要再补充。
Slerp 函数是非常常用的一个函数,用来产生旋转。
static function Slerp (from : Quaternion, to : Quaternion, t : float) : Quaternion
对于新手来说,最难的莫过于如何用它产生一个匀速的旋转。如果想用它产生匀速转动,最简单的办法就是把form和to固定,然后匀速增加t
var obj1: T
var obj2:Transform;
var speed:
var t=0.1;
q=Quaternion.Slerp(obj1.rotation, obj2.rotation,t);
transform.rotation=q;
t+=Time.deltaT
但是这并不能解决所有情况。 很多时候from 和to都不是固定的,而且上一个脚本也不能保证所有角度下的旋转速度一致。所以我写了这个脚本来保证可以应付大多数情况。
var target: T
var rotateSpeed=30.0;
var wantedRotation=Quaternion.FromToRotation(transform.position,target.position);
t=rotateSpeed/Quaternion.Angle(transform.rotation,wantedRotation)*Time.deltaT
q=Quaternion.Slerp(transform.rotation, target.rotation,t);
transform.rotation=q;
这个脚本可以保证物体的旋转速度永远是rotateSpeed。
第七行用旋转速度除以两者之间的夹角得到一个比例。
如果自身坐标和目标之间的夹角是X度,我们想以s=30度每秒的速度旋转到目标的方向,则每秒旋转的角度的比例为s/X。 再乘以每次旋转的时间Time.deltaTime我们就得到了用来匀速旋转的t值
阅读(...) 评论()

我要回帖

更多关于 unity3d slerp 的文章

 

随机推荐