编写Unity3D脚本 - 打开门不会停止旋转
Scripting Unity3D - Opening door does not stop rotating
对.. 这是我第一次在这里提问,如果我遗漏了任何重要细节,我深表歉意,我会尽力提供相关信息。
这是我的问题:我正在使用门脚本来打开橱柜,其中一扇门工作正常。然而,另一扇门是镜像的,并沿着相同的旋转方向打开,使其向内而不是向外打开。
我的猜测(请注意,作为一个完全的初学者)是
openRot = new Vector3 (defaultRot.x, defaultRot.y + DoorOpenAngle, defaultRot.z
需要更改为负的 DoorOpenAngle(只需将 + 替换为 - 即可翻转旋转方向)。
然而,这反而让门旋转得非常快,而且它不会停止 "opening",它只是在无限循环中不断旋转完整的 360 度。下面的脚本是门正常工作的脚本,如果我按照我上面的建议将角度更改为负值,还有什么可能是门一直不停的原因?
我猜还有另一段代码由于尝试简单的镜像旋转而存在冲突,抱歉,如果根据您自己的标准这看起来很乱,请在格式上尽力而为。
var smooth = 2.0;
var DoorOpenAngle = 90.0;
private var open : boolean;
private var enter : boolean;
private var defaultRot : Vector3;
private var openRot : Vector3;
function Start()
{
defaultRot = transform.eulerAngles;
openRot = new Vector3 (defaultRot.x, defaultRot.y + DoorOpenAngle, defaultRot.z);
}
//Main function
function Update (){
if(open)
{
//Open door
transform.eulerAngles = Vector3.Slerp(transform.eulerAngles,
openRot, Time.deltaTime * smooth);
}
else
{
//Close door
transform.eulerAngles = Vector3.Slerp(transform.eulerAngles,
defaultRot, Time.deltaTime * smooth);
}
if(Input.GetKeyDown("f") && enter){
open = !open;
}
}
function OnGUI(){
if(enter){
GUI.Label(new Rect(Screen.width/2 - 75, Screen.height - 100, 150, 30), "Press 'F' to open the cabinet");
}
}
你误解了什么Slerp
does. You're expecting it to behave more like RotateTowards
。
Slerp
,像任何 线性插值 函数一样,采用两个值 from
和 to
,然后 returns 另一个值那是他们之间的 t
%。这有时非常有用,但并不是您真正想要做的,在这里。
另一方面,RotateTowards
取两个值 current
和 target
,然后将 current
向 target
旋转最多 maxRadiansDelta
和 returns 那。这更接近您正在寻找的行为。
由于我们正在处理旋转,因此使用起来会更容易 Quaternion.RotateTowards
。基本概念是一样的。
假设您希望门每秒旋转 30 度:
//convert euler angles to quaternion
//you can do this earlier, but this is fine for now
var openRotQ = Quaternion.Euler(openRot);
//calculate rotation
var maxDegrees = Time.deltaTime * 30;
var newRot = Quaternion.RotateTowards(transform.rotation, openRotQ, maxDegrees);
//apply rotation
transform.rotation = newRot;
如果这些更改后它仍然无法正常工作,请注意 Unity 的文档建议您避免角度超过 360 度 when working with Euler angles。
您可以通过为您希望应用的每个旋转构建一个单独的四元数来解决这个问题:
//compose and apply a separate quaternion for rotation
var rotated = transform.rotation * Quaternion.Euler(0, DoorOpenAngle, 0);
openRot = rotated.eulerAngles;
对.. 这是我第一次在这里提问,如果我遗漏了任何重要细节,我深表歉意,我会尽力提供相关信息。
这是我的问题:我正在使用门脚本来打开橱柜,其中一扇门工作正常。然而,另一扇门是镜像的,并沿着相同的旋转方向打开,使其向内而不是向外打开。
我的猜测(请注意,作为一个完全的初学者)是
openRot = new Vector3 (defaultRot.x, defaultRot.y + DoorOpenAngle, defaultRot.z
需要更改为负的 DoorOpenAngle(只需将 + 替换为 - 即可翻转旋转方向)。
然而,这反而让门旋转得非常快,而且它不会停止 "opening",它只是在无限循环中不断旋转完整的 360 度。下面的脚本是门正常工作的脚本,如果我按照我上面的建议将角度更改为负值,还有什么可能是门一直不停的原因?
我猜还有另一段代码由于尝试简单的镜像旋转而存在冲突,抱歉,如果根据您自己的标准这看起来很乱,请在格式上尽力而为。
var smooth = 2.0;
var DoorOpenAngle = 90.0;
private var open : boolean;
private var enter : boolean;
private var defaultRot : Vector3;
private var openRot : Vector3;
function Start()
{
defaultRot = transform.eulerAngles;
openRot = new Vector3 (defaultRot.x, defaultRot.y + DoorOpenAngle, defaultRot.z);
}
//Main function
function Update (){
if(open)
{
//Open door
transform.eulerAngles = Vector3.Slerp(transform.eulerAngles,
openRot, Time.deltaTime * smooth);
}
else
{
//Close door
transform.eulerAngles = Vector3.Slerp(transform.eulerAngles,
defaultRot, Time.deltaTime * smooth);
}
if(Input.GetKeyDown("f") && enter){
open = !open;
}
}
function OnGUI(){
if(enter){
GUI.Label(new Rect(Screen.width/2 - 75, Screen.height - 100, 150, 30), "Press 'F' to open the cabinet");
}
}
你误解了什么Slerp
does. You're expecting it to behave more like RotateTowards
。
Slerp
,像任何 线性插值 函数一样,采用两个值 from
和 to
,然后 returns 另一个值那是他们之间的 t
%。这有时非常有用,但并不是您真正想要做的,在这里。
RotateTowards
取两个值 current
和 target
,然后将 current
向 target
旋转最多 maxRadiansDelta
和 returns 那。这更接近您正在寻找的行为。
由于我们正在处理旋转,因此使用起来会更容易 Quaternion.RotateTowards
。基本概念是一样的。
假设您希望门每秒旋转 30 度:
//convert euler angles to quaternion
//you can do this earlier, but this is fine for now
var openRotQ = Quaternion.Euler(openRot);
//calculate rotation
var maxDegrees = Time.deltaTime * 30;
var newRot = Quaternion.RotateTowards(transform.rotation, openRotQ, maxDegrees);
//apply rotation
transform.rotation = newRot;
如果这些更改后它仍然无法正常工作,请注意 Unity 的文档建议您避免角度超过 360 度 when working with Euler angles。
您可以通过为您希望应用的每个旋转构建一个单独的四元数来解决这个问题:
//compose and apply a separate quaternion for rotation
var rotated = transform.rotation * Quaternion.Euler(0, DoorOpenAngle, 0);
openRot = rotated.eulerAngles;