Making an object spin 360 as it moves towards new Vector3.

Hi,

I’m trying to learn how to do rotations like how you can translate a gameObject to a new Vector3.

In this example, I’m trying to make a cube rotate 360 degrees as it moves to a new Vector3.

I’m a little lost but feel I could learn a lot about rotation if I can learn this one example.

Any feedback would be great.

using UnityEngine;
using System.Collections;

public class SpinForward : MonoBehaviour {

    GameObject player;
    public float moveSpeed;
    new Vector3 Goal = new Vector3(3, 6, 0);
    //new Quaternion Spin = new Quaternion (0, 360, 0, 0);
    new Quaternion Spin = Quaternion.Euler(0, 360, 0);

    // Use this for initialization
    void Start () {
        player = GameObject.Find("player");
        transform.rotation = Quaternion.Euler(0,0,0);
    }
  
    // Update is called once per frame
    void Update () {
        if (Input.GetMouseButtonDown(0))
        {
            player.transform.position = Vector3.MoveTowards(player.transform.position, Goal, moveSpeed * Time.deltaTime);
            player.transform.rotation = Quaternion.RotateTowards (player.transform.rotation, Spin, moveSpeed * Time.deltaTime);
        }
    }
}
1 Like

This:

new Quaternion Spin = Quaternion.Euler(0, 360, 0);

is exactly the same as:

new Quaternion Spin = Quaternion.Euler(0, 0, 0);

So your object is probably starting with a 0,0,0 rotation and your rotating towards the spot it already is.
Now Quaternion.RotateTowards is just meant to rotate your object till it faces a specific direction. Is that what your trying to achieve?

Or do you just want it to spin in place while the button is down?
If you just want it to spin in place you want to use transform.Rotate

//Vector3.up is shorthand for (0,1,0)
//Basically we are rotating around the Y-axis
float degreesPerSecond = 20;
transform.Rotate(Vector3.up*degreesPerSecond*Time.DeltaTime);

If you wanted it to tumble in all 3 directions

transform.Rotate(new Vector3(1f,1f,1f,)*degreesPerSecond*Time.deltaTime;

Thanks for the feedback.

I just want the cube object to roll towards the new Vector3.

It rotates on the Y axis as it moves Towards a new vector3. And then it stops rotating.

LIKE THROWING A DICE.

Sorry about shouting, but I am excited to realise such a simple analogy shows what I mean.

Then its basically what I gave you but a different axis you rotate about. Also in Unity is a left hand rule system where positive X is to the right. positive Z is straight forward and positive Y is straight up.

If you spin around the Y axis you twirl in place like a ballerina
if you spin around the Z axis you twist about like doing a cartwheel.
if you spin about the X axis you will roll along the ground.

Now this only works to spin along the world X axis if we are facing directly forward along the world Z Axis.
Fortunately each object’s transform keeps track of its own personal Forward (z) , Up (y) and Right(x) axis

So to make sure we roll as we move we first need to Look at the thing we are rolling towards:

transform.Lookat(Goal);

Now that we are facing the right way we use this:

transform.Rotate(transform.right*moveSpeed*time.deltaTime);

Now to put it all together:

void Update () {
        if (Input.GetMouseButtonDown(0))
        {
            player.transform.LookAt(Goal);
            player.transform.position = Vector3.MoveTowards(player.transform.position, Goal, moveSpeed * Time.deltaTime);
            player.transform.Rotate(player.transform.right*moveSpeed*Time.deltaTime);
        }
    }

Technically we only want to look at our Goal once. If we keep looking at it each time we’ll reset our roll to the start. So we need to catch the single frame they press the button down like this:

void Update () {
         // this is true the one frame they click the button
         if (input.GetMouseButton(0))
         {
                  player.transform.LookAt(Goal);
        }
        // this is true as long as the button is held down
        if (Input.GetMouseButtonDown(0))
        {
            player.transform.position = Vector3.MoveTowards(player.transform.position, Goal, moveSpeed * Time.deltaTime);
            player.transform.Rotate(player.transform.right*moveSpeed*Time.deltaTime);
        }
    }

Finally, you might want to have all this happen with just one button click, not have the user constantly hold down the mouse button. That is what Coroutines are for:

void Update () {
         // this is true the one frame they click the button
         if (input.GetMouseButton(0))
         {
                  player.transform.LookAt(Goal);
                  StartCoroutine(MoveCube());
        }
}

IEnumerator MoveCube()
{
          while (player.tranform.position != Goal)
          {
                 player.transform.position = Vector3.MoveTowards(player.transform.position, Goal, moveSpeed * Time.deltaTime);
player.transform.Rotate(player.transform.right*moveSpeed*Time.deltaTime);
            // this says yield control back to Unity until the
            // next frame.. but pick up right here when we get
            // called again
            yield return null;
           }
    }
1 Like

Thanks for your time and knowledge.

I only want to learn.

I’m blown away by this function degreesPerSecond.
It’s so useful.
I’d never heard of it.

I take it, it’s a function inherited from monobehavior to be used for rotations?

If your referring to this:

float degreesPerSecond = 20; // <--- just a variable i made up
transform.Rotate(Vector3.up*degreesPerSecond*Time.DeltaTime);

degreesPerSecond is just a variable. it happens to hold how many degrees I want to turn each second so I called it that. That code easily could have been written like this:

float a = 20;
transform.Rotate(Vector3.up*a*Time.DeltaTime);

But I find degreesPerSecond to be more descriptive when reading than “a”

When you use transform.rotate the actual function is this
transform.Rotate(Vector3, degrees)

It will spin you around the Vector3 you pick (in our case we chose Vector3.up the world UP axis).
Now the number of degrees you pick is how many degrees you you will spin around.
if you do this;

transform.Rotate(Vector3.up, 10);

You will always rotate 10 degrees.
Time.deltaTime gives us the time since the last Update call (Each frame). When time.DeltaTime = 1 that means its been 1 second. (Usually it will equal like .02 seconds)
So when we call Rotate if we muliply 10*time.deltaTime it will Rotate us 10 degrees in 1 second, or whatever small part of that it needs in the .02 seconds that have passed.

So if you set degreesPerSecond = 20 then use my code above you spin 20 degrees per second. If you change that number to 100 you spin 100 degrees per second.

1 Like