this.transform.Rotate(0, 0, -2, Space.Self);
transform.rotation = Quaternion.Euler(transform.eulerAngles + new Vector3(0, 0, 2));
this.transform.localEulerAngles = new Vector3(this.transform.localEulerAngles.x, this.transform.localEulerAngles.y, this.transform.localEulerAngles.z + 3);
Vector3.RotateTowards
Quaternion.LookRotation(direction);
quaternion.lerp
quaternion.slerp
其实说白了,LookRotation的含义就是,计算让Z轴对齐forward,让y轴对齐upward 所需要的旋转四元数。
此函数作用是生成一个四元数表示的三维朝向,然后可以直接把这个朝向赋给游戏对象来变更其朝向,也可以通过线性插值(Quaternion.Slerp 和 Quaternion.Lerp)来实现游戏对象从当前朝向转到这个新生成的朝向上来。
在做游戏时会发现有些跟随动作不够圆滑或者需要一个缓冲的效果,这时,一般会考虑到插值。所以对插值的理解是必需的。(比如摄像机跟随主角)。
在unity3d中用函数Lerp()来在两者之间插值,两者之间可以是两个材质之间、两个向量之间、两个浮点数之间、两个颜色之间,其函数原型如下:
static Vector3 Lerp(Vector3 from, Vector3 to, float t);
Material.Lerp 插值 (在两个材质之间插值)
Vector2.Lerp 插值 (两个向量之间的线性插值)
Vector3.Lerp 插值 (3D空間中两个向量之间的线性插值)
Mathf.Lerp 插值 (基于浮点数t返回a到b之间的插值)
Color.Lerp 插值 (通过t在颜色a和b之间插值)
首先还是先从数学的角度来看一下什么是插值运算:
线性插值法(linear interpolation) : 线性插值法是指使用连接两个已知量的直线来确定在这两个已知量之间的一个未知量的值的方法。
假设我们已知坐标(x0,y0)与(x1,y1),要得到[x0,x1]区间内某一位置x在直线上的值。根据图中所示,我们得到两点式直线方程:
假设方程两边的值为α,那么这个值就是插值系数—从x0到x的距离与从x0到x1距离的比值。由于x值已知,所以可以从公式得到α的值
线性插值公式:
Y= Y0+(Y1-Y0)*埃尔法
总结吐糟:插值也就是个距离百分比,所有当然在0-1之间了,所以unity也是这么定义的
在函数中: from + (to - from) * t;这也就是Lerp的返回值。from 是起始的位置,to是目标位置,按照数字t在from到to之间插值。这句话比较难理解,下面举个例子:
void Update() {
transform.position= Vector3.Lerp(start.position, end.position, Time.time);
}}
在1秒时间动画位置移动从from开始到to结束。(这是官方的例子)
如果不是Time.time,而是0.5,会怎么样?(只看一个变量)
由图易知:A物体会不断以0.5的比例无限接近于B,会导致物体在移动的时候会越来越慢。像弹簧一样。
参考: http://www.cnblogs.com/unity3ds/p/5737183.html
-------------------------------------------------------------------------------------------------
以下内容未测试
但是如果需求是匀速平滑到某点,这咋办呢?
void Update() {
t += 1f / mMoveTime * Time.deltaTime;//线性系数随时间每秒增加相同倍数
from.position = Vector3.Lerp(mStartPos, to.position, t);//匀速变化
}
如果我想要他移动到指定位置后继续保持匀速运动怎么做呢。因为系数的取值范围是0~1,也就是说>1的值它会忽略掉
这时候使用公式就可以了:from.position = mStartPos + (to.position - mStartPos) * t;
下面贴几个代码来看下其他属性里面的插值效果:
float time = 1f; //何秒かけて色を変えるか
void Update () {
if (started && diffTime <= 1f) {
diffTime = (Time.realtimeSinceStartup - startTime)/time; //变化时间
circle.color = Color.Lerp (Color.white, Color.black, diffTime);
}
}
Renderer sphere; //模型的渲染组件
[SerializeField]
Material mat1, mat2; //定义材质球
void Start(){
sphere = GetComponent<Renderer> ();
}
void Update () {
if (started && diffTime <= 1f) {
diffTime = (Time.realtimeSinceStartup - startTime)/time;
sphere.material.Lerp (mat1, mat2, diffTime/);
}
}
void Update () {
transform.position = new Vector3 (Mathf.Lerp (-5f,5f, Mathf.PingPong(Time.time,1)),0f,0f);
}
[SerializeField]
Quaternion from, to;
void Start () {
from = this.transform.rotation;
to = Quaternion.Euler (90, 0, 0); //x軸90度
}
void Update () {
if (started && this.transform.rotation != to) {
diffTime = Time.realtimeSinceStartup - startTime;
transform.rotation = Quaternion.Lerp (from, to, diffTime);
}
}
使用线性插值还可以实现让物体做弧线运动 如炮弹发射后的飞行痕迹
- using UnityEngine;
- using System.Collections;
- public class MoveCurve : MonoBehaviour {
- public GameObject t1; //开始位置
- public GameObject t2; //结束位置
- // Update is called once per frame
- void Update () {
- //两者中心点
- Vector3 center = (t1.transform .position + t2.transform.position) * 0.5f;
- center -= new Vector3(0, 1, 0);
- Vector3 start = t1.transform.position - center;
- Vector3 end = t2.transform.position - center;
- //弧形插值
- transform.position = Vector3.Slerp(start,end,Time.time);
- transform.position += center;
- }
- }