角度边界问题
注意:尽管这个问题是在我使用 Unity 时出现的,但它与 Unity 没有任何特定关系,更多的是关于编程逻辑,所以请不要回避。
我正在使用 Unity 并通过脚本旋转对象。问题是,如果我将其旋转到 180 度,该对象不会精确旋转到那么多,并且往往会停在 179 到 181 度之间。因此,为了检查旋转是否完成,我检查旋转角度是否为 targetAngle +/- 1,这有效。
我检查使用
if (transform.eulerAngles.z > lowerLimit && transform.eulerAngles.z < upperLimit)
where
lowerLimit = targetAngle-1;
upperLimit = targetAngle + 1;
现在,当 targetAngle 为 0 时就会出现问题。在这种情况下,我的脚本检查旋转角度是否在 -1 和 1 之间。但是,-1 实际上应该是 359,因此需要检查角度是否位于359 和 1 之间。
我该如何实现这个? 换句话说,我想我是在问如何实现环绕数字系统。
编辑
找到一种解决方法。如果targetAngle为0,我会特殊对待。它可以工作,但不是最优雅的。
if (targetAngle == 0.0)
{
if ((transform.eulerAngles.z > 359.0 && transform.eulerAngles.z <= 360.0) || (transform.eulerAngles.z >= 0.0 && transform.eulerAngles.z <= 1))
{
rotate = false;
}
}
else
{
if (transform.eulerAngles.z > targetAngle - 1 && transform.eulerAngles.z < targetAngle + 1)
{
rotate = false;
}
}
Heads up: Even though this problem arose while I was working with Unity, it has nothing specific to Unity, and is more about programming logic, so please don't shy away.
I'm using Unity and rotating an object by script. The thing is, if I rotate it to, say, 180 degrees, the object does not rotate exactly to that much and tends to stop at between 179 and 181 degrees. So, to check if rotation is complete I check if the rotation angle is targetAngle +/- 1, which works.
I check using
if (transform.eulerAngles.z > lowerLimit && transform.eulerAngles.z < upperLimit)
where
lowerLimit = targetAngle-1;
upperLimit = targetAngle + 1;
Now, the problem arises when the targetAngle is 0. In this case, my script checks if rotation angle is between -1 and 1. But, -1 should really be 359, so it needs to check if the angle lies between 359 and 1.
How can I implement this?
In other words, I guess I'm asking how to implement a wrap-around number system.
EDIT
Found one work-around. If targetAngle is 0, I treat is specially. It works, but isn't the most elegant.
if (targetAngle == 0.0)
{
if ((transform.eulerAngles.z > 359.0 && transform.eulerAngles.z <= 360.0) || (transform.eulerAngles.z >= 0.0 && transform.eulerAngles.z <= 1))
{
rotate = false;
}
}
else
{
if (transform.eulerAngles.z > targetAngle - 1 && transform.eulerAngles.z < targetAngle + 1)
{
rotate = false;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以这样做...
这将使支票远离零,并且您不必处理正/负检查。
编辑
targetAngle
上的%
运算符将旋转限制为 +/-359 度,因此 721 的目标角度将降至 1, -359 的目标角度将降至 1。我认为这对于所有情况都应该很好。编辑2
要修复您在评论中提到的最后一种情况,我想您需要对
transform.eulerAngles.z
值应用相同的包装逻辑。现在可能最好将此包装放入额外的函数中,因此请尝试以下操作:根据您需要使用此功能的频率,检查某些情况可能会消除不必要的开销。例如,仅当输入为正时才需要wrappNumber 中的最后一个
% 360
。如果您每分钟调用此命令十次,那可能并不重要。如果您每秒调用它一百次,您可能需要检查它在这种情况下的执行情况。You could do ...
This moves the check away from the zero and you wouldn't have to deal with positive/negative checking.
EDIT
The
%
operator on thetargetAngle
restricts the rotating to +/-359 degrees, so a target angle of 721 would come down to 1, and a target angle of -359 would come down to 1. This should do nicely for all cases I think.EDIT 2
To fix the last case you mentioned in your comment, I guess you'd need to apply the same wrapping logic to your
transform.eulerAngles.z
values. Probably best to put this wrapping in an extra function now, so try this:Depending on how often you need to use this, checking for some cases might remove unneeded overhead. For example, the final
% 360
within wrapNumber is only needed if the input was positive. If you're calling this ten times per minute it probably won't matter. If you're calling it a hundred times per second, you may want to check how it performs in this situation.这可能是一个旧线程,但在查看了许多不同的片段(都试图处理 Wrapping)之后,我发现 Unity 有一个很好的内置函数,可以简单地处理业务,至少在我的情况下,我需要的最终结果是一个 lerp,所以我只需要将其更改为 LerpAngle,它就返回了可靠的结果。
Mathf.LerpAngle 是你的朋友..解决了我所有的弹出问题等..
http:// docs.unity3d.com/ScriptReference/Mathf.LerpAngle.html
This may be an old thread but after looking at many different snippets all trying to deal with Wrapping I found that Unity has a nice builtin function that simply takes care of business, At least in my case that the end result i required was a lerp so i only had to change it to LerpAngle and it returned a solid result.
Mathf.LerpAngle is your friend.. solved all my issues with popping etc..
http://docs.unity3d.com/ScriptReference/Mathf.LerpAngle.html