我在这里是新手,我尝试开始使用Unity Engine。
有人可以解释一下,Quaternion.Slerp如何工作?因为我想以90、180和270度的角度旋转某个对象。我的代码如下所示。不幸的是,当我增加180度时,对象会做出疯狂的事情,而不是将此游戏对象的旋转度设为(0,180,180)。我想得到(180,0,0)
public float speed = 0.1F; private float rotation_x; void Update() { if (Input.GetButtonDown("Fire1")) { rotation_x = transform.rotation.eulerAngles.x; rotation_x += 180; } transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(rotation_x, transform.eulerAngles.y, transform.eulerAngles.z), Time.time * speed); }
那里的大多数示例,包括其官方网站上的Unity示例,都以错误的方式使用了Lerp。他们甚至不费心地在API文档中描述它的工作方式。他们只是将其添加到Update()函数中,并称之为一天。
Update()
Mathf.Lerp,Vector3.Lerp以及Quaternion.Slerp通过从一个位置/旋转变换到另一种与工作 吨 值(最后一个参数)被传递in.That 吨 值也被知道为时间。
Mathf.Lerp
Vector3.Lerp
Quaternion.Slerp
所述的最小 吨 值是 0F 和max为 1F 。
我将对此进行解释,Mathf.Lerp以使其更易于理解。该Lerp功能是所有的,两者相同Mathf.Lerp,Vector和Quaternion。
Lerp
Vector
Quaternion
请记住,这Lerp需要两个值并在它们之间返回值。如果我们的值是 1 和 10 ,则对它们执行Lerp:
float x = Mathf.Lerp(1f, 10f, 0f); will return 1. float x = Mathf.Lerp(1f, 10f, 0.5f); will return 5.5 float x = Mathf.Lerp(1f, 10f, 1f); will return 10
正如你所看到的,t(0)返回 分钟 传入的数量,t(1)返回的 最大 传入值,并t(0.5)返回 中旬 的点之间的 最小 和 最大 的价值。当传递任何 t 值< 0或时,您做错了> 1。Update()函数中的代码就是这样做的。Time.time会每秒增加,并且会> 1在一秒内增加,因此您会遇到问题。
t(0)
t(1)
t(0.5)
< 0
> 1
Time.time
建议Lerp在其他功能/协程中使用而不是更新功能。
注意事项 :
Lerp在旋转方面,使用有不好的一面。Lerp不知道如何以最短的路径旋转对象。所以请记住这一点。例如,您有一个带有0,0,90位置的对象。假设您要将旋转方向从移到,0,0,120 Lerp有时可以向左旋转而不是向右旋转才能到达新位置,这意味着到达该位置需要更长的时间。
0,0,90
0,0,120
假设我们(0,0,90)要从当前旋转角度开始旋转。以下代码将0,0,90在3秒内将旋转更改为。
(0,0,90)
随时间旋转 :
void Start() { Quaternion rotation2 = Quaternion.Euler(new Vector3(0, 0, 90)); StartCoroutine(rotateObject(objectToRotate, rotation2, 3f)); } bool rotating = false; public GameObject objectToRotate; IEnumerator rotateObject(GameObject gameObjectToMove, Quaternion newRot, float duration) { if (rotating) { yield break; } rotating = true; Quaternion currentRot = gameObjectToMove.transform.rotation; float counter = 0; while (counter < duration) { counter += Time.deltaTime; gameObjectToMove.transform.rotation = Quaternion.Lerp(currentRot, newRot, counter / duration); yield return null; } rotating = false; }
随时间增加的角度旋转:
要将对象沿z轴旋转到90度,下面的代码就是一个很好的例子。请理解将对象移动到新的旋转点与仅旋转它之间有区别。
void Start() { StartCoroutine(rotateObject(objectToRotate, new Vector3(0, 0, 90), 3f)); } bool rotating = false; public GameObject objectToRotate; IEnumerator rotateObject(GameObject gameObjectToMove, Vector3 eulerAngles, float duration) { if (rotating) { yield break; } rotating = true; Vector3 newRot = gameObjectToMove.transform.eulerAngles + eulerAngles; Vector3 currentRot = gameObjectToMove.transform.eulerAngles; float counter = 0; while (counter < duration) { counter += Time.deltaTime; gameObjectToMove.transform.eulerAngles = Vector3.Lerp(currentRot, newRot, counter / duration); yield return null; } rotating = false; }
我所有的示例均基于设备的帧频。您可以通过将替换Time.deltaTime为来使用实时功能,Time.delta但需要更多的计算。
Time.deltaTime
Time.delta