【问题标题】:Rotate GameObject back and forth来回旋转游戏对象
【发布时间】:2017-04-26 08:13:00
【问题描述】:

我想在 Y 轴上在 90,-90 之间来回旋转一个对象。问题是我可以在编辑器中将对象设置为 -90,但是当我运行项目时,-90 突然变成 270。无论如何这里是我正在使用的代码:

void Update()
{
    if (transform.eulerAngles.y >= 270)
    {
        transform.Rotate(Vector3.up * speed * Time.deltaTime);
    }
    else if (transform.eulerAngles.y <= 90)
    {
        transform.Rotate(Vector3.up * -speed * Time.deltaTime);

    }
}

它总是卡在 360 度左右的中间。帮忙?

【问题讨论】:

  • 理论上它应该停留在 360 和 0 之间,因为当旋转达到 360 度时,您的代码建议:&gt;= 270 所以继续旋转,使旋转为 0,然后你的代码说:现在是&lt;= 90,所以向后旋转,再次使其成为 360,等等。

标签: c# unity3d rotation euler-angles


【解决方案1】:

就像moving GameObject 来回旋转一样,您可以使用Mathf.PingPong 来回旋转 GameObject。这就是它的用途。它将返回 0 和 1 之间的值。您可以将该值传递给 Vector3.Lerp 并生成执行旋转所需的 eulerAngle。

这也可以通过协程完成,但如果您不需要知道何时到达目的地,则应使用Mathf.PingPong。如果您想知道何时到达轮换目的地,则应使用协程。

public float speed = 0.36f;

Vector3 pointA;
Vector3 pointB;


void Start()
{
    //Get current position then add 90 to its Y axis
    pointA = transform.eulerAngles + new Vector3(0f, 90f, 0f);

    //Get current position then substract -90 to its Y axis
    pointB = transform.eulerAngles + new Vector3(0f, -90f, 0f);
}

void Update()
{
    //PingPong between 0 and 1
    float time = Mathf.PingPong(Time.time * speed, 1);
    transform.eulerAngles = Vector3.Lerp(pointA, pointB, time);
}

编辑:

使用coroutine 方法,您可以使用该方法来确定每次轮换的结束。

public GameObject objectToRotate;
public float speed = 0.36f;

Vector3 pointA;
Vector3 pointB;


void Start()
{
    //Get current position then add 90 to its Y axis
    pointA = transform.eulerAngles + new Vector3(0f, 90f, 0f);

    //Get current position then substract -90 to its Y axis
    pointB = transform.eulerAngles + new Vector3(0f, -90f, 0f);

    objectToRotate = this.gameObject;
    StartCoroutine(rotate());
}

IEnumerator rotate()
{
    while (true)
    {
        //Rotate 90
        yield return rotateObject(objectToRotate, pointA, 3f);
        //Rotate -90
        yield return rotateObject(objectToRotate, pointB, 3f);

        //Wait?
        //yield return new WaitForSeconds(3);
    }
}

bool rotating = false;
IEnumerator rotateObject(GameObject gameObjectToMove, Vector3 eulerAngles, float duration)
{
    if (rotating)
    {
        yield break;
    }
    rotating = true;

    Vector3 newRot = gameObjectToMove.transform.eulerAngles + eulerAngles;

    Vector3 currentRot = gameObjectToMove.transform.eulerAngles;

    float counter = 0;
    while (counter < duration)
    {
        counter += Time.deltaTime;
        gameObjectToMove.transform.eulerAngles = Vector3.Lerp(currentRot, newRot, counter / duration);
        yield return null;
    }
    rotating = false;
}

【讨论】:

  • 我对“Mathf.PingPong”很熟悉,但我不想使用它,因为我想在每个回合之间添加一个延迟,稍后我可能会将整个逻辑移动到一个协程中。我更愿意使用 if 语句来准确地知道我何时达到特定程度来实现我的目标。
  • 我知道并且我在回答中提到了所有这些。您的问题仅表示您想来回移动。没有其他的。甚至您的代码也有一个来回脚本。下次在您的问题中添加更多详细信息会很好。检查我对协程方法的更新答案。
  • 你看到修改后的答案了吗?
  • 是的,我从中吸取了一些原则并将它们应用到我的代码中。起初它没有像我预期的那样工作。谢谢。
【解决方案2】:

首先,您应该始终确保角度保持在0 和359 之间,这意味着0 == 360:

float angle = transform.eulerAngles.y % 360.00f;

之后,您可以检查它是否在介于您的最小值和最大值之间:

if ( angle >= 270.00f &&  angle <= 90.00f )
{
    // do your logic here ...
}

您的代码的另一个问题是它会卡在350 和10 度之间。为了更详细地解释这一点,我们假设你的速度是10,Time.deltaTime 也是1,起始角度是300,现在帧步数:

 Frame | Angle | Condition 
 ----- | ----- | :-----------:
    1  | 300   | angle >= 270  
    2  | 310   | angle >= 270  
    3  | 320   | angle >= 270  
    6  | 350   | angle >= 270  
    7  | 360   | angle >= 270  
    8  |  10   | angle <= 90   
    9  |   0   | angle <= 90   
   10  | 350   | angle >= 270  

...这将永远持续下去。

要解决这个问题,您必须根据用户输入设置一些条件,或者如果您希望您的相机在这两个角度之间“反弹”,那么您可以尝试这样的事情:

// make private field in that object :
float currentlyRotated = 0;
bool shouldAdd = true;

void Update()
{
    var d = Vector3.up * (shouldAdd ? speed : -speed) * Time.deltaTime;
    var angle = transform.eulerAngles.y + (shouldAdd ? speed : -speed);
    angle %= 360.00f;

    transform.Rotate(d);

    if ( angle > 90 && angle < 270 )
    {
        shouldAdd = !shouldAdd;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多