Rotate GameObject back and forth

大憨熊 提交于 2019-11-27 08:12:25

问题


I would like to rotate an object back and forth between 90,-90 on the Y axis. The problem is I can set the object in the editor at -90, but when I run the project -90 suddenly becomes 270. Anyway here is the code that I'm using:

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);

    }
}

It always gets stuck in the middle around 360 degrees. Help?


回答1:


Just like moving GameObject back and forth, you can rotate GameObject back and forth with Mathf.PingPong. That's what it is used for. It will return value between 0 and 1. You can pass that value to Vector3.Lerp and generate the eulerAngle required to perform the rotation.

This can also be done with a coroutine but Mathf.PingPong should be used if you don't need to know when you have reached the destination. Coroutine should be used if you want to know when you reach the rotation destination.

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);
}

EDIT:

With the coroutine method that you can use to determine the end of each rotation.

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;
}



回答2:


First of all you should always ensure that the angle stays between 0 and 359, meaning that 0 == 360 :

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

After that you can check if it's between your minimum and maximum value :

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

Another issue with your code is that it will stuck somewhere between 350 and 10 degrees. To explain this in more details let's assume your speed is 10, Time.deltaTime will be 1 as well and starting angle is 300, now frame steps :

 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  

... and this will go forever.

To deal with this you have to make some condition based on user input or if you want your camera to "bounce" between these two angle then you can try something like this :

// 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;
    }
}


来源:https://stackoverflow.com/questions/43628472/rotate-gameobject-back-and-forth

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!