#1 Rotate Translate函数只是一次改变旋转和位置 是因为放在了Update函数里才使其有了平滑的连续的动画效果
如果把Rotate函数放在Start()函数里 旋转值会立刻改变 没有过渡。
#2
插值类函数 (Interpolating Functions)
Mathf.Lerp(a,b,t)
当t<0 时 t按0计算 当t>1时 t按1计算 当t属于[0,1]时 函数的返回值为a+(b-a)*t 连续的Update调用使其产生平滑过渡的效果。
类似的还有Vector3.Lerp Color.Lerp Quaternion.Lerp
有个类似但又不同的函数 Mathf.MoveTowards
static float MoveTowards(float current, float target, float maxDelta);
是以maxDelta为增量进行值的改变 当maxDelta为负时 current将远离target
static Vector3 MoveTowards(Vector3 current, Vector3 target, float maxDistanceDelta);
按直线把一个点从current移动到target 返回值是从current到target直线上离current距离为maxDistanceDelta的点的坐标
如果两点的连线距离不足maxDistanceDelta,则直接到达target 也就是说返回值永远不会超过target. 如果是maxDistanceDelta是负值 则current点将按直线远离target.
如print(Vector3.MoveTowards(new Vector3(0,0,0),new Vector3(3,4,0),1)); 结果是 (0.6,0.8,0.0)
同样有个类似的函数Mathf.MoveTowardsAngle
static float MoveTowardsAngle(float current, float target, float maxDelta);
和MoveToward类似 但是确保当超过360度时按照角度的方式计算 由于优化原因 不支持负的maxDelta
current和target代表的角都是以角度为单位的、所以要注意:旋转角度之间的插值应该用MoveTowardsAngle 类似的函数还有Mathf.LerpAngle
球形插值Vector3.Slerp与线性插值Lerp不同之处在于将传入的向量当做方向处理 而非原来当做点来处理 且它的模也会被插值处理。
反过来计算需要多少插值参数才能从current到target的函数 Mathf.InverseLerp(from,to,value)
如 print(Mathf.InverseLerp(5,10,8)); 结果为(8-5)/(10-5)=0.6
Summary:
Lerp类函数:
Mathf.Lerp()
Vector3.Lerp()
Color.Lerp()
Quaternion.Lerp()
对应的角度插值函数为
Mathf.LerpAngle()
Slerp类函数
Vector3.Slerp()
MoveTowards类函数
Mathf.MoveTowards()
Vector3.MoveTowards()
对应的角度插值函数为
Mathf.MoveTowardsAngle()
反插值函数
Mathf.InverseLerp()
夹逼函数
Mathf.Clamp
static float Clamp(float value, float min, float max);
static int Clamp(int value, int min, int max);
将value夹在min和max之间 如果value < min 则 返回min 如果value > max 则返回max 不改变value的值
static float Mathf.PingPong(float t,float length)
返回值将在[0,length]之间有序来回震荡 注意要放在Update()函数里面
如
void Update() {
transform.position = new Vector3(Mathf.PingPong(Time.time, 3), transform.position.y, transform.position.z);
}
让物体的x坐标在[0,3]来回震荡。
Transform.Translate()
重载1:
void Translate(Vector3 translation, Space relativeTo = Space.Self);
移动位移translation 默认是自身坐标系
相对:
coordinate(坐标)
Space.Self 自身坐标系
Space.World 世界坐标系
重载2:
void Translate(float x, float y, float z, Space relativeTo = Space.Self);
沿x轴位移x 沿y轴位移y 沿z轴位移z
重载3:
void Translate(Vector3 translation, Transform relativeTo);
位移向量translation 以relativeTo的局部坐标为参照 如果relativeTo为null 则以世界坐标为参照系。
重载4:
void Translate(float x, float y, float z, Transform relativeTo);
Transform.Rotate()
重载1:void Rotate(Vector3 eulerAngles, Space relativeTo = Space.Self);
按照欧拉角旋转物体(z,x,y) 注意顺序(旋转顺序不同最终旋转效果也可能不同) 单位是角度
类似于Translate 默认是物体自身的局部坐标系
注意:以世界坐标旋转并不是绕着世界坐标轴旋转 而只是按照世界坐标系的方向 以自身枢轴点旋转。
重载2:void Rotate(float xAngle, float yAngle, float zAngle, SpacerelativeTo = Space.Self);
绕z轴z度 绕x轴x度 绕y轴y度 注意顺序
重载3:void Rotate(Vector3 axis, float angle, Space relativeTo = Space.Self);
绕axis向量旋转angle度 默认axis向量的坐标系是物体自身的局部坐标系
Unity中采用左手坐标系
Vector3类
普通成员变量:
x y z 分量
this[index] (0:x 1:y 2:z)
eg:
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour {
public Vector3 p;
void Example() {
p[1] = 5; //将向量p的y分量置为5
}
}
只读:
magnitude 模sqrMagnitude 模的平方(效率)
normalized 标准化向量
静态成员变量:
zero (0,0,0)
one (1,1,1)
缩写(shorthand)静态数据成员不用new
static Vector3 right;:Shorthand for writing Vector3(1, 0, 0). x轴
static Vector3 up; : Shorthand for writing Vector3(0, 1, 0).y轴
static Vector3 forward;:Shorthand for writing Vector3(0, 0, 1). z轴
对应的有left(-1,0,0) down(0,-1,0)back(0,0,-1)
构造函数
重载1 Vector3(float x,float y ,float z)
重载2 Vector3(float x,float y)
sets z to zero
普通成员函数:
void Set(float new_x, float new_y, float new_z);
重新为一个已存在的向量设置x y z分量
静态函数:
static float Angle(Vector3 from, Vector3 to); 返回from和to的夹角 (单位为度 不大于180度)
static Vector3 ClampMagnitude(Vector3 vector, float maxLength); 返回一个向量的拷贝 其模长不超过maxLength
static Vector3 Cross(Vector3 lhs, Vector3 rhs); 叉乘
static float Distance(Vector3 a, Vector3 b); 返回 a b 两点的距离 与(a-b).magnitude 作用相同
static float Dot(Vector3 lhs, Vector3 rhs); 点乘
static Vector3 Lerp(Vector3 from, Vector3 to, float t); 线性插值
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour {
public Transform startMarker;
public Transform endMarker;
public float speed = 1.0F;
private float startTime;
private float journeyLength;
void Start() {
startTime = Time.time;
journeyLength = Vector3.Distance(startMarker.position, endMarker.position);
}
void Update() {
float distCovered = (Time.time - startTime) * speed;
float fracJourney = distCovered / journeyLength;
transform.position = Vector3.Lerp(startMarker.position, endMarker.position, fracJourney);
}
}
static Vector3 Max(Vector3 lhs, Vector3 rhs); 返回模较大的向量static Vector3 Min(Vector3 lhs, Vector3 rhs); 返回模较小的向量
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour {
public Transform target;
public float speed;
void Update() {
Vector3 targetDir = target.position - transform.position;
float step = speed * Time.deltaTime;
Vector3 newDir = Vector3.RotateTowards(transform.forward, targetDir, step, 0.0F);
Debug.DrawRay(transform.position, newDir, Color.red);
transform.rotation = Quaternion.LookRotation(newDir);
}
static Vector3 Scale(Vector3 a, Vector3 b);
a和b的各分量对应相乘得到一个新的向量
如
print(Vector3.Scale(new Vector3(1, 2, 3), new Vector3(2, 3, 4)));
输出 (2.0,6.0,12.0) 用于各个方向的缩放操作
static Vector3 Slerp(Vector3 from, Vector3 to, float t);
模拟日出日落效果
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour {
public Transform sunrise;
public Transform sunset;
public float journeyTime = 1.0F;
private float startTime;
void Start() {
startTime = Time.time;
}
void Update() {
Vector3 center = (sunrise.position + sunset.position) * 0.5F;
center -= new Vector3(0, 1, 0);
Vector3 riseRelCenter = sunrise.position - center;
Vector3 setRelCenter = sunset.position - center;
float fracComplete = (Time.time - startTime) / journeyTime;
transform.position = Vector3.Slerp(riseRelCenter, setRelCenter, fracComplete);
transform.position += center;
}
}
static Vector3 SmoothDamp(Vector3 current, Vector3 target, Vector3 currentVelocity, float smoothTime, float maxSpeed = Mathf.Infinity, floatdeltaTime = Time.deltaTime);
弹簧效果的阻尼 先快后慢 速度是ref
smoothtime 从current到达target大约需要耗费的时间
deltaTime 上一次函数调用至此次调用间隔的时间间隔
The most common use is for smoothing a follow camera.
运算:
- :向量减法 反向量
!=:Very close vectors are treated as being equal.
*:向量的数乘 注意只定义了Vector3与float的乘法 double没有
/:static Vector3 operator /(Vector3 a, float d); 向量的数除
+:向量的加法 对应分量相加
==:This will also return true for vectors that are really close to being equal.
由此可见 Unity中的Vector3的==已经考虑了浮点比较误差 因此我们不需要像C语言那样通过epsilon的约束来比较两个浮点数
Quaternion类
用来表示旋转 没有欧拉角的Gimbal Lock(万向节死锁)问题 易插值计算 Unity内部旋转处理方式
四元数:
1概念 Q=[w,(x,y,z)] 一个四元数包含一个标量分量和一个三维向量分量
在3D数学中用单位四元数来表示旋转 对于旋转轴为n=(nx,ny,nz) 旋转角度为α的旋转 用四元数表示:
w=cos(α/2)
x=sin(α/2)Nx
y=sin(α/2)Ny
z=sin(α/2)Nz
简记为 Q=[cos(α/2),sin(α/2)n]
一般为了计算方便 要求n为单位矢量
静态成员变量:
identity:无旋转 (Read Only) 实验得值为(0,0,0,1) (x,y,z,w)
普通成员变量:
Vector3 eulerAngles 返回对应的欧拉角 旋转顺序为 z x y 即物体在Inspector显示的Rotation的转换成-180-180范围后的结果
this[int] :获取分量 x y z w 对应 0 1 2 3
x y z w :float
构造函数
Quaternion(x,y,z,w)
成员函数
void Set(float new_x, float new_y, float new_z, float new_w);
为一个已经存在的四元数设置x,y,z,w;
void SetFromToRotation(Vector3 fromDirection, Vector3toDirection);
将当前四元数设置为一个从from旋转到to方向的旋转
如:
public Quaternion rotation = Quaternion.identity;
void Start()
{
rotation.SetFromToRotation(new Vector3(0, 1, 0), new Vector3(0, 0, 1));
print(rotation.eulerAngles);
}
应该绕x轴旋转90度 所以输出(90.0,0.0,0.0) 旋转轴是(1,0,0) 所以rotation被设置成(0.707(cos(90/2)),0,0,0.707) 符合前面四元数的概念定义。
void SetLookRotation(Vector3 view, Vector3 up = Vector3.up);
设置朝向一个位置的旋转 即令物体的z轴对准view物体 x轴与up垂直 这个函数一般用于令物体面对另一物体
http://blog.youkuaiyun.com/lijing_hi/article/details/7272089
如果view 是 零向量 将抛出一个提示信息
up可以是零向量 表示对x轴的朝向没有要求
void ToAngleAxis(float angle, Vector3 axis);
把一个四元数表示的旋转转换成角-轴表示的形式
out参数 注意是ToAngleAxis 而非ToAxisAngle 后者已经过时
静态成员函数
static float Angle(Quaternion a, Quaternion b);
返回两个旋转z轴的夹角 单位是度
如
print(Quaternion.Angle(new Quaternion(0, 0, 0, 1), new Quaternion(0,Mathf.Sqrt(2)/2,0,Mathf.Sqrt(2)/2))); 输出为90
static Quaternion AngleAxis(float angle, Vector3 axis);
返回一个绕axis轴旋转angle度的等价的Quaternion旋转
如 print(Quaternion.AngleAxis(90, Vector3.up)); 输出(0.0,0.7,0.0,0.7)
static float Dot(Quaternion a, Quaternion b);
static Quaternion Euler(float x, float y, float z);
static Quaternion Euler(Vector3 euler);
由一个绕z轴z度 x轴x度 y轴y度得到的旋转转换成Quaternion
static Quaternion FromToRotation(Vector3 fromDirection, Vector3toDirection);
类似SetFromToRotation
static Quaternion Inverse(Quaternion rotation);
返回一个旋转的逆
static Quaternion Lerp(Quaternion from, Quaternion to, float t); 从from到to之间用t插值然后将结果标准化,该函数比Slerp处理速度更快 但是当from和to相隔较远时效果较差。
static Quaternion LookRotation(Vector3 forward, Vector3 upwards= Vector3.up);
类似SetLookRotation函数
static Quaternion RotateTowards(Quaternion from, Quaternion to, float maxDegreesDelta);
将旋转from旋转到to
通过一个角位移maxDegreesDelta来进行旋转 注意不会越界 单位是角度
如果角位移是负的 那么from将远离to 直到to的反向为止(为止的意思是停止运动 实验得到会在附近有轻微的震荡)
static Quaternion Slerp(Quaternion from, Quaternion to, float t);
球形差值
eg
using UnityEngine; using System.Collections; public class ExampleClass : MonoBehaviour { public Transform from; public Transform to; public float speed = 0.1F; void Update() { transform.rotation = Quaternion.Slerp(from.rotation, to.rotation, Time.time * speed); } }运算:
!= :该函数通过判断两个Quaternion的Dot Product是否小于1.0来运作。
注意:因为quaternion能够表示两圈内的旋转(720) 所以即使两者的旋转效果看起来不一样 比较结果也可能返回true.
*:结合两个旋转 a*b 效果是 先旋转a 后旋转b (!= b * a)不满足交换律 类似于矩阵的乘法效果
==:注意:因为quaternion能够表示两圈内的旋转(720) 所以即使两者的旋转效果看起来一样 比较结果也可能返回false 比如旋转 10度和旋转370度
cos5° 不等于 cos185° Dot == 1.0 则两者相等
.