我是 Unity 新手,我可以获得帮助吗?
所以基本上我创建了一个钟摆,但我添加了一些功能,如果它达到可能的最大高度,钟摆的 Y 轴将旋转 180 度,但 Y 轴不旋转。
这是代码:
using UnityEngine;
public class PendulumScript : MonoBehaviour
{
[SerializeField] public float speed = 1.5f;
public float limit = 75f;
public bool randomStart = false;
private float random = 0;
private bool limitReached = false;
private Quaternion originalRotation;
void Awake()
{
if (randomStart)
{
random = Random.Range(0f, 1f);
}
// Save the original rotation
originalRotation = transform.localRotation;
}
void Update()
{
float angle = limit * Mathf.Sin(Time.time + random * speed);
transform.localRotation = Quaternion.Euler(0, 0, angle);
if (!limitReached && (angle == limit))
{
// Rotate around the Y-axis by 180 degrees
transform.Rotate(0, 180 * Time.time, 0);
limitReached = true;
limit *= -1; // turns limit into negative
}
else if (limitReached && (angle == -limit))
{
// Reset to original rotation which is Y = 0
transform.localRotation = originalRotation;
limitReached = false;
limit *= -1; // turns limit into positive
}
}
}
我正在尝试使用
if !limitreached and else if limitreached
进行旋转,它确实旋转但闪烁,因为它一直在旋转,这就是为什么我添加了另一个条件,但似乎我能想到的最佳条件不起作用,我希望找出 (angle == limit)
条件有什么问题,即它没有得到满足,或者也许它不起作用的真正原因是什么。
所以,如果我没说错的话,你想要的实际上是两次旋转
您的方法存在各种问题
这个
transform.localRotation = Quaternion.Euler(0, 0, angle);
是不是
only rotate on the Z axis
!重置相当困难y = 0
。
切勿使用
float
来比较==
!
由于精度限制,这可能永远不会是
true
您的状况也仅在最多一帧期间
true
。
您更想触发围绕 Y 的连续旋转
我也这么认为
Time.time + random * speed
不完全是您想要使用的,而是例如
(Time.time + random) * speed
还有
transform.Rotate(0, 180 * Time.time, 0);
是否不旋转180°...时间越长,它在这里旋转得越多!
我实际上会将其视为两个单独的轮换并分别处理它们:
public class PendulumScript : MonoBehaviour
{
public float speed = 1.5f;
public float limit = 75f;
public bool randomStart = false;
private float rotationZ;
private float rotationY;
private bool performingYFlip;
private float time;
private float targetYRotation;
void Awake()
{
// instead of selecting a random sin value
// I would rather select a random start time
// This way you have a clear check when enough time has passed to
// perform the flip
if(randomStart)
{
// sinus range is in radians => full cycle every 2π
time = Random.Range(0f, 2 * Mathf.PI) * speed;
}
}
void Update()
{
// simply increase the timer by the time passed since last frame
time += Time.deltaTime * speed;
// calculate Z rotation as before
rotationZ = Mathf.Sin(time) * limit;
// Use approximate equality for angles
// note that due to the sinus even this might never be true within a frame
//if(Mathf.Approximately(rotationZ, limit))
// so you might even use a wider range like e.g.
if(Mathf.Abs(rotationZ - limit) <= /*Some Threshold in angles*/ 5f)
{
performingYFlip = true;
targetYRotation += 180f;
}
if(performingYFlip)
{
yRotation = Mathf.MoveTowards(yRotation, targetYRotation, yRotationSpeed * Time.deltaTime);
if(Mathf.Approximately(yRotation, targetYRotation))
{
performingYFlip = false;
}
}
// and finally apply both rotations together
transform.rotation = Quaternion.Euler(0, yRotation, zRotation);
}
}