Unity C# 带旋转的摆锤

问题描述 投票:0回答:1

我是 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)
条件有什么问题,即它没有得到满足,或者也许它不起作用的真正原因是什么。

c# unity-game-engine quaternions
1个回答
0
投票

所以,如果我没说错的话,你想要的实际上是两次旋转

  • 摆锤绕Z轴连续前后旋转
  • 此外,一旦达到任一侧的极限,您还需要在 Y 上旋转 180°

您的方法存在各种问题

  • 这个

    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);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.