0

So I am trying to rotate an object on key press (if I press "a" rotate left by 90 degree, if I press "d" rotate right by 90 degree). I can't make it to work, I have tried a few things but I ended up not solving the problem. As you will see in the next example I only figure out how to rotate TO 90 degree, not more or less, I actually want to rotate the object BY 90 degrees, from whichever degree was currently on. For example: from 90 degree to 180 degree from 23 degree to 113 degree and so on... here is my code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ModuleBehaviour : MonoBehaviour {

    public bool rotating = false;


    private void Update()
    {
        if (rotating)
        {
            RotatePlatform();
        }
    }

    private void RotatePlatform()
    {
        Vector3 target = new Vector3(0,0,90);
        if (transform.eulerAngles.z > 90)
        {
            transform.rotation = Quaternion.Euler(target);

        }
        transform.Rotate(target * Time.deltaTime);
    }
}

(Don't bother about the rotating variable, I am changing it in another script, it get's true whenever I press the "d" key. I only need to know how to rotate in the right direction, after that I will figure it out how to apply for left rotation)

Thank you;

Noobie
  • 45
  • 8
  • Coroutine + Lerp. Read from the **INCREMENTAL ANGULAR ROTATION OVER TIME:** in the duplicate and you will see how to rotate an object by 90 degree from whichever angle it already is at. – Programmer Jan 16 '18 at 23:13

2 Answers2

2

This will do what you want:

private IEnumerator RotatePlatform(float dir) {
    Vector3 target = new Vector3(0, 0, (transform.eulerAngles.z + dir + 360) % 360);
    while(Mathf.Abs(transform.eulerAngles.z - target.z) >= Mathf.Abs(dir * Time.deltaTime * 2)) {
        transform.Rotate(new Vector3(0,0,dir) * Time.deltaTime);
        yield return null;
    }
    transform.eulerAngles = target;
    rotating = false;
}

The key things to take away from this is that I encapsulated the "make it animate" code into a coroutine so that the object rotates to the desired direction from any starting rotation to any rotation in either direction. The reason this works is that the coroutine's local variables hold their state between iterations (the Unity scheduled task system will halt executing the code on a yield instruction and resume at a later time: in this case, null means it will resume on the next frame). This way we can store the starting rotation and target rotation without having to do anything crazy.

It does this by getting the current rotation, adding the rotation amount, then making that value lie within 0-360: transform.eulerAngles.z + dir + 360) % 360. transform.eulerAngles.z will already be [0,360], subtracting 90 from that would leave [-90,270], then by adding 360 we insure that the value will always be greater than 0 (without affecting the resulting angle), then % 360 effectively subtracts off any excess quantities of 360.

The Mathf.Abs(transform.eulerAngles.z - target.z) >= Mathf.Abs(dir * Time.deltaTime * 2) statement checks to see if the "distance we have yet to rotate" is "greater than the amount we're going to rotate by" with some buffer: we don't want to overshoot and have our "how far do we need to go" be 358 degrees!

The other important change was that we want to use new Vector3(0,0,dir) rather than target as our value to rotate by so that the speed remains constant.

The last 2 instructions make sure the rotation actually achieves the desired value and, of course, toggle back the bool tracking whether or not pressing keys does anything (we only want 1 instance of our coroutine).

Then here's the Update() method I used to control it:

private void Update() {
    if(!rotating) {
        if(Input.GetKeyDown(KeyCode.D)) {
            rotating = true;
            StartCoroutine(RotatePlatform(90));
        }
        if(Input.GetKeyDown(KeyCode.A)) {
            rotating = true;
            StartCoroutine(RotatePlatform(-90));
        }
    }
}
  • THANK YOU! I adapted the code to suit my needs and it works LIKE A CHARM! The algorithm is perfect! – Noobie Jan 17 '18 at 09:41
0

To rotate in the other direction, subtract 90.

void Update()
{
    if (Input.GetKeyDown(KeyCode.D))
        transform.Rotate(0, 0, transform.rotation.z + 90);
}
ryeMoss
  • 4,303
  • 1
  • 15
  • 34
  • Yhea I know that but I don't want to rotate it like that, I don't want to know the previous angle, I just want to rotate the object by 90 degree from whichever angle it already is at... – Noobie Jan 16 '18 at 21:40
  • this will rotate it from 90 degrees at whatever it is at. – ryeMoss Jan 16 '18 at 23:49