1

I'm watching unity tutorials and in the control code of the ship I would like to make it rotate on its axis, that is, it can rotate 360 ​​degrees continuously while I press the right key for example.

playerController:

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

[System.Serializable]
public class Boundary
{
    public float xMin, xMax, zMin, zMax;
}

public class PlayerController : MonoBehaviour {

    [Header("Movement")]
    public float speed;
    public float tilt;
    public Boundary boundary;
    private Rigidbody rig;

    [Header("Shooting")]
    public GameObject shot;
    public Transform shotSpawn;
    public float fireRate;
    private float nextFire;

    void Awake () {
        rig = GetComponent<Rigidbody>();
    }

    void Update () {
        if (Input.GetButton ("Fire1") && Time.time > nextFire) {
            nextFire = Time.time + fireRate;
            Instantiate (shot, shotSpawn.position, Quaternion.identity);
        }
    }

    void FixedUpdate () {
        float moveHorizontal = Input.GetAxis ("Horizontal");
        float moveVertical = Input.GetAxis ("Vertical");
        Vector3 movement = new Vector3(moveHorizontal, 0f, moveVertical);
        rig.velocity = movement * speed;
        rig.position = new Vector3 (Mathf.Clamp (rig.position.x, boundary.xMin, boundary.xMax), 0f, Mathf.Clamp (rig.position.z, boundary.zMin, boundary.zMax));
        rig.rotation = Quaternion.Euler (0f, 0f, rig.velocity.x * -tilt);
    }
}

How can I edit it to do what I want?

example:

enter image description here

Meta Code
  • 557
  • 1
  • 7
  • 15

2 Answers2

3

You can use Transform.Rotate()

Your code would look like this, with the example you provided:

  void FixedUpdate () {
    float moveHorizontal = Input.GetAxis ("Horizontal");
    float moveVertical = Input.GetAxis ("Vertical");
    Vector3 movement = new Vector3(moveHorizontal, 0f, moveVertical);
    rig.velocity = movement * speed;
    rig.position = new Vector3 (Mathf.Clamp (rig.position.x, boundary.xMin, boundary.xMax), 0f, Mathf.Clamp (rig.position.z, boundary.zMin, boundary.zMax));
    if(moveHorizontal > 0){ //if your "right key" is pressed
      // Rotate the object around its local X axis at 1 degree per second
      transform.Rotate(Vector3.right * Time.deltaTime);
    }
}

For faster Rotation you can simply multiply the Vector3.right with some value.

To Rotate around another Axis, use other Vector directions, like Vector3.up. For example:

transform.Rotate(Vector3.Up * moveHorizontal * Time.deltaTime);
transform.Rotate(Vector3.Forward * moveHorizontal * Time.deltaTime);

When you multiply the Vector3.Right with your moveHorizontal it should also work when you press the "left key" and that should result in rotating in the other direction.

 transform.Rotate(Vector3.right * moveHorizontal * Time.deltaTime);

Notes:

That only works if your PlayerController is attached to your ship gameobject. If it is not attached you have to use the transform of your ship of course.

World Space vs Local Space

When you click on your object in the scene view, you should see the transform and the 3 arrows (red, green, blue) pointing on different directions (the 3 axis). When you use the method with the parameters provided above, you are using these arrows as rotation axis.

You can also rotate arround the WorldSpace axis.

transform.Rotate(Vector3.up, Time.deltaTime, Space.World);

When to use transform.Rotate?

When you change position or rotation of a transform, using the transforms methods, it will be applied at the end of the frame. These changes ignore physics.

-> Use transforms methods if you don't care about collisions

When to use rigidbody.MoveRotation?

When you change rigidbody.position or rigidbody.MoveRotation using rigidbodies methods, it will be applied at the end of the next physics step. These changes care about physics (collisions and stuff)

-> Use rigidbodies methods if you care about collisions

Thanks to Helium for that hint.

The third possibility:

Instead of directly calling transform.Rotate or rigidbody.MoveRotation, you can also rotate your Object, using an animation, which changes the transforms rotation.

Example of Transform.Rotate()

You can clearly see, that the collision checks are ignored on that object while it's rotating through the ground. (I packed that gif into a spoiler to reduce noise. You'll need to hover over it, if you want to see it)

gif showing transform rotate

Tobias Theel
  • 3,088
  • 2
  • 25
  • 45
  • Tobias, you'l alright, but I already tried to use the transform rotate, but I can not do it, try to do as you said but it does not work. i have the ship and only need to rotate himself like a spin ( in the direction i press obviously ) – Meta Code Mar 04 '18 at 05:18
  • How does your ship behave, when you use transform rotate? That method should be able to create the behavior you desire. I'll try to help you solve this problem, if you give me more information :) – Tobias Theel Mar 04 '18 at 12:11
  • 1
    Because the ship relies on a Rigidbody (and thus, may need to detect collision), using `transform.Rotate` is a bad idea because the physics engine may not detect collision correctly. Instead, [rigidbody.MoveRotation](https://docs.unity3d.com/ScriptReference/Rigidbody.MoveRotation.html) should be used – Hellium Mar 04 '18 at 12:19
  • It is only a bad idea when you care about collision while rotating. But +1 for that useful piece of information – Tobias Theel Mar 04 '18 at 12:23
  • 1
    Tobias, thats very helpful, ( to clarify ) i update the post, you can see the gif there. thanks :b – Meta Code Mar 04 '18 at 17:00
  • You need to rotate arround another Axis. You may want to try Vector3.Forward and/or Vector3.Up as axis to rotate around - just change the axis in the Transform.Rotate method with one of these values. I guess one of these 2 axis should fit your needs. – Tobias Theel Mar 04 '18 at 17:37
2

This will be the speed and axis of your rotation.

public Vector3 eulerAngleVelocity = new Vector3(0f,0f,1000f);

Since you want to rotate a rigidbody so use MoveRotation

Quaternion deltaRotation = Quaternion.Euler(-moveHorizontal * eulerAngleVelocity * Time.deltaTime);
rig.MoveRotation(rig.rotation * deltaRotation);

Final code will look like this

    // NEW CODE BEGIN------
public Vector3 eulerAngleVelocity = new Vector3(0f,0f,1000f);
// NEW CODE END------

void FixedUpdate () {
    float moveHorizontal = Input.GetAxis ("Horizontal");
    float moveVertical = Input.GetAxis ("Vertical");
// NEW CODE BEGIN------
    Vector3 movement = new Vector3(0f, 0f, moveVertical); // Notice I have removed moveHorizontal, this will make sure your gameobject doesnt go left and right. We will use move horizontal for rotating the gameobject.
// NEW CODE END------
    rig.velocity = movement * speed;
    rig.position = new Vector3 (Mathf.Clamp (rig.position.x, boundary.xMin, boundary.xMax), 0f, Mathf.Clamp (rig.position.z, boundary.zMin, boundary.zMax));
    // NEW CODE BEGIN------
    Quaternion deltaRotation = Quaternion.Euler(-moveHorizontal * eulerAngleVelocity * Time.deltaTime);
    rig.MoveRotation(rig.rotation * deltaRotation);
    // NEW CODE END------
}

You can play with eulerAngleVelocity to get the desired speed. Hope this helps. ;)

  • thats preety close but, i want to rotate in this way https://media.giphy.com/media/xkPF1gjoukkZ3UBp1r/giphy.gif – Meta Code Mar 04 '18 at 17:02
  • 1
    There might be many ways to do this, I can think of two of it right now. Try and see 1) Enable 'IsKinematic' on the rigidbody and try but this will make the object fix to its position. 2) Alternatively you can make your movement vector like this ` Vector3 movement = new Vector3(0f, 0f, moveVertical);` i.e. only move in Z axis and set IsKinematic to false in rigidbody. – Imran Hashmi Mar 04 '18 at 21:32
  • sorry, can you explain me the second way? im very new in this – Meta Code Mar 05 '18 at 01:02
  • I have edited the above code. so if you select your PlayerController gameobject you can see in the inspector there is a rigidbody attached to it. Just make sure 'IsKinematic' is unchecked. Then replace your FixedUpdate with the code above. – Imran Hashmi Mar 05 '18 at 15:42