【问题标题】:Scripting Unity3D - Opening door does not stop rotating脚本 Unity3D - 打开门不会停止旋转
【发布时间】:2015-03-21 05:04:36
【问题描述】:

好吧..这是我第一次在这里提问,如果我遗漏了任何重要细节,我深表歉意,我会尽力提供相关信息。

这是我的问题:我正在使用脚本打开一个柜子的门,而一扇门可以正常工作。然而,另一扇门是镜像的,并沿相同的旋转打开,使其向内而不是向外打开。
我的猜测(作为一个完整的初学者,请注意)是

    openRot = new Vector3 (defaultRot.x, defaultRot.y + DoorOpenAngle, defaultRot.z

需要更改为负 DoorOpenAngle(只需将 + 替换为 - 即可翻转旋转方向)。
然而,这反而使门旋转得非常快,并且不会停止“打开”,它只是在无限循环中保持完整的 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");
  }
}

【问题讨论】:

  • 我相信那是 Javascript,而不是 Java。我不相信 Unity 使用 Java 作为其脚本语言。
  • 谢谢,实际上不知道两者之间有区别;)更改了问题的标题。
  • 实际上是 UnityScript,而不是 JavaScript(或者 ECMAScript,如果我们要准确的话):wiki.unity3d.com/index.php/UnityScript_versus_JavaScript
  • 哇,我也不知道...实际上我不是试图编程的人,我正在帮助一个朋友。我个人根本没有任何编码经验,我只是阅读并基本了解逻辑。感谢您澄清它是什么语言。做这件事的中间人并不容易。
  • 不明白为什么这对打开或关闭都有效。更新循环不断地调用Slerp。 deltaTime 是自上一帧以来的时间。尝试记录按下“f”键的时间然后Slerp 基于从那时起经过的时间,而不是 deltaTime。

标签: unity3d unityscript


【解决方案1】:

你误解了Slerp 的作用。您希望它的行为更像RotateTowards

Slerp 与任何线性插值 函数一样,接受两个值fromto,然后返回另一个值,即它们之间的百分比为t。有时这非常有用,但不是您真正想要做的,在这里。

另一方面,RotateTowards 采用两个值 currenttarget,然后将 currenttarget 旋转最多 maxRadiansDelta 并返回。这更接近您正在寻找的行为。

由于我们正在处理旋转,因此使用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;

【讨论】:

  • 其实我很了解它的作用,它是四元数函数我还没有理解 ;) 就像我之前在评论中提到的那样,我不是真正的编码器.. 我只是倾向于更好地理解我所看到的东西的人,但是由于我刚搬到国外,因此我目前正在等待发货,因此,我没有自己测试事物所需的硬件。我一直认为四元数会更有意义,但由于我缺乏知识,我无法正确整合它。
  • 我在回答中又添加了一条建议。您没有提到这是一个问题,但这是我从提供的信息中看到的唯一其他问题。
  • 是的,我们计划明天使用您的答案来解决这个问题。感谢您提供详细信息!而且我们还没有使用过 360 度以上的任何东西。我的第一个想法是将 90 更改为 270(将其停在正确的位置),但这并没有改变它的旋转方式。一旦我们弄清楚如何翻转方向,门就完全翻转了,这毫无意义。第一个工作得很好,所以我认为没有理由开始干预四元数,但我们会看看情况如何。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-28
  • 2023-03-16
  • 1970-01-01
  • 2020-03-24
相关资源
最近更新 更多