Rotating a spaceship

In a top-down retro-style space exploration game, your space ship should rotate based on the direction your moving. How can that be accomplished with a C# script?

You like press left, so spaceship moves left and rotates over time to that direction or how?

if that is the case you can lerp LookAt function

Yes that’s what I was looking for. Thanks

Nope that’s not working, but what you described is the way i want it to move. Can you be more specific as what to try doing?

IEnumerator LookTo(Vector3 startPos, Vector3 endPos, float overTime)
    {
        float i = 0f;
        while (i <= overTime)
        {
            transform.eulerAngles = Vector3.Lerp(startPos, endPos, i/overTime);
            i += Time.deltaTime;
            yield return null;
        }
        transform.eulerAngles =endPos;
        yield return null;
    }

Use this if you are just moving left right. Over time is float and it represents how much time will pass while he rotates. for startPos send transform.eulerAngles and for endPos send wanted euler.

in practice

if (input for right)
{
   StartCorutine(LookTo(transform.eulerAngles, new Vector3(transform.eulerAngles.x, transform.eulerAngles.y, 0f), 0.5f)
}

this will rotate object to “Right” or 0 degress over 0.5 seconds (0 goes for angle that needs to be rotated but for 2d mostly it is z axis) left is 180, up is 90 down 270

(btw i copied this from my move script and replaced position with eulerAngles but should work :slight_smile:

nope not working. all its doing is…preventing me from moving forward? Not sure why. Is this code written for a 2D top-down game?

well then problem is not in this script, except you would need to set flag. like canmove = false when press and at the end of IEnumator before yield return null; add canmove = true. also there is no 2d just 3d in unity, just there is 2d simulation so it feels like 2d and have some 2d tools to make 2d making easier.
this code should work, its just how you implemented it in your code

is there a simpler way? like changing the values of transform.rotation via script a small amount until it reaches the direction of movement?

LookAt() will work fine, but you need to set the second parameter to what is considered “up” in your world space. I haven’t made a 2D game, but judging by how it’s placed in the 3D space in the editor, I’d guess that “up” is actually “Vector3.back” in that case. You may have to play with it. One thing to keep in mind in a 2D game is that X and Y are used, but Z isn’t (I think), which means that any scripts that use Vector3.forward as a general guideline for “ahead” (Z+) are going to be wrong, because “up” on the screen is actually Y+ instead.

Is there a way to change the values of transform.rotation similar to the way you would change transform.position?

ok here’s the very simple code i’ve been using for movement:

void Update () {
        if (canmove) {
            if (Input.GetAxisRaw ("Vertical") == 1) {
                Vector3 pos = gameObject.transform.position;
                pos.y += 0.02f;
                gameObject.transform.position = pos;
            }
            else if (Input.GetAxisRaw ("Vertical") == -1) {
                Vector3 pos = gameObject.transform.position;
                pos.y -= 0.02f;
                gameObject.transform.position = pos;
            }
            if (Input.GetAxisRaw ("Horizontal") == 1) {
                Vector3 pos = gameObject.transform.position;
                pos.x += 0.02f;   
                gameObject.transform.position = pos;
            }
            else if (Input.GetAxisRaw ("Horizontal") == -1) {
                Vector3 pos = gameObject.transform.position;
                pos.x -= 0.02f;
                gameObject.transform.position = pos;
            }
        }
    }

Now what should i do to have the ship rotate with movement?

Well you can

StartCorutine(Rotate ("right"));

then

IEnumator Rotate (string direction)
{
   switch (direction)
   {
    case "right"
      if (tranform.eulerAngles.y => 0.5f && transform.eulerAngles.y <= 359.5f)
      {
          transfrom.Rotate(0,0.2f,0);
          yield WaitForSeconds(0.1f);
          StartCorutine(Rotate("right"));
      }

do case for each side (left, right …), you need to play with numbers and which axis to rotate since i had to use z in one project and lysander said y. it depends

You’re doing frame-rate dependent movements btw- you have no way of knowing how many times Update is going to get called per second, and it’s going to fluctuate, which means your movements will slow down/speed up based on the whims of the program. You need to place the movements in FixedUpdate or multiply them based on Time.deltaTime (the time it took the last frame to process), which will balance them out.

That is quite bad movement script.
all 3 rows could be replaced with
transfrom.rotation += new Vector3 (0, 0.02f, 0)
replace vector3 cordinates with each direction you go, btw 0.02f is really small nomber, how fast you enable moving?

Yea, it is pretty slow for good reason: I’m building the game using graphics on a small scale.
and yea my coding needs some work

yeah i was wondering same but isnt important in small games as, i still didnt see problems of update for such and still use it (update)

Actually no, i just forgot to use fixed update :stuck_out_tongue:

Time.timeScale affects the way that time is processed by the game, so even if it’s not important now it will become important when you have small points of lag or find that you need to stop time and such later on (even in small games). FixedUpdate is affected by the change in time, while the framerate (and thus the Update function) aren’t.

Ok heres the updated code

if (canmove) {
            if (Input.GetAxisRaw ("Vertical") == 1) {
                transform.position += new Vector3 (0, 0.02f, 0);
            }
            else if (Input.GetAxisRaw ("Vertical") == -1) {
                transform.position += new Vector3 (0, -0.02f, 0);
            }
            if (Input.GetAxisRaw ("Horizontal") == 1) {
                transform.position += new Vector3 (0.02f, 0, 0);
            }
            else if (Input.GetAxisRaw ("Horizontal") == -1) {
                transform.position += new Vector3 (-0.02f, 0, 0);
            }
        }

Now could you please show me how to implement that code you’ve written. Sorry, I’ve tried and apparently i’m getting it wrong.

Here is better solution. Set at initialization int direction; then for example at first vertical 1 after moving do this
If (direction != 0){
InvokeRepeating(“Rotate”,0f, 0.1f);
direction = 0;
}

Then make function
void Rotate(){
switch(direction)
case 0:
If (tranform.eulerAngles.y < 89.5)
transform.Rotate(0,0.1f,0);
else if (tranform.eulerAngles.y > 90.5)
transform.Rotate(0,-0.1f,0);
break;

Now do so for every case like 0 is up 1 is left Nd so on. I cant write much iam on phone ;p