Get the FULL version

Unity: Rotation Controller

Unity: Rotation Controller thumbnail

Another day, another Unity3D programming post. This tutorial contains not just one, but two scripts that rotates a game object around another one, based on the keyboard input. Again, like the previous tutorial, this was also inspired by retro games, such as S.T.U.N. Runner or the special stages from Sonic 2, where the player controls the main character by pressing left or right, making it complete a full circle in the screen. However, unlike those games, the below scripts aren’t applying gravity to the player, for the sake of simplicity. Everything explained here is available for download at the end of the tutorial.

For both of the scripts, we are going to need two game objects: the first is going to be the player, and the other one will be the pivot that the player rotates around. The process of creating both is the same, just click on GameObject->Create Other->Cube twice, naming the first one as Player and the other one as Player Pivot:

Creating a Cube game object screenshot

Repeat this process twice. Name the game objects 'Player' and 'Player Pivot'.

The Player Pivot game object will act as the rotation pivot for the Player game object. Now place both game objects at the same position, and center then at the world origin (X:0, Y:0, Z:0). The last thing to do is to move the camera to focus both objects and move the Player game object only at the Y axis, as shown:

Positioning the 'Player' game object screenshot

The 'Player' (blue cube) is at Y: -3.5, while the 'Pivot' (green cube) is at the world origin (Y: 0.0).

The last thing to prepare on the scene is to assign a new tag to the Pivot game object, naming it Pivot. After creating it, assign the tag to the Pivot game object.

Creating a tag screenshot

Create a tag by clicking on the 'Tag' dropdown menu on the 'Player Pivot' Inspector.

Finally, it is now possible to attach one of the scripts to the Player game object. The first one will rotate the player around the pivot counterclockwise when pressing left and clockwise when pressing right:

using UnityEngine;
using System.Collections;

public class RotationControllerSimple : MonoBehaviour
{
	//the containing game object's Transform
	private Transform goTransform;
	//the pivot which the game object should rotate around at
	private Transform pivotTransform;
	//the velocity to rotate the game object
	public float vel = 2.0f;

	void Awake()
	{
		//get the game object's Transform
		goTransform = this.GetComponent<Transform>();
		//get the pivot's Transform
		pivotTransform = GameObject.FindWithTag("Pivot").GetComponent<Transform>();
	}

	// Update is called once per frame
	void FixedUpdate ()
	{
		//rotate the player around the pivot
		goTransform.RotateAround(pivotTransform.position, Vector3.forward, Input.GetAxisRaw("Horizontal")*vel);
	}
}

This simple script will work as described. Lines 7,9 and 11 declare two Transforms and a float. The first two are variables that will hold the containing game object Transform and the pivot game object Transform respectively. The third one is a float that determines the velocity in which the Player should rotate. The Awake() method, initializes the two Transform variables (lines 13 through 19). After that, the FixedUpdate() method just makes the attached game object (the Player) rotate around the Player Pivot game object at the determined speed (lines 22 through 26).

That works as expected, however, the above script will only rotate the object clockwise and counterclockwise with the left and right arrow keys, meaning that when the controllable object is over top half of the screen, the controls, will appear to be inverted, as shown:

Inverted Keys screenshot

In that case, left is right and right is left.

While this is still a correct behavior, it can be counterintuitive for some players. And that’s the reason why we may need another script, that will invert the controls when the controllable game object is over the top half of the screen:

using UnityEngine;
using System.Collections;

public class RotationControllerRelative : MonoBehaviour
{
	//the containing game object's Transform
	private Transform goTransform;
	//the pivot which the game object should rotate around at
	private Transform pivotTransform;
	//the velocity to rotate the game object
	public float vel = 2.0f;
	//a boolean that flags if the player is at the top side of the screen
	private bool topSide = false;
	//the direction (clockwise or counter clockwise)
	float motionDirection;

	void Awake()
	{
		//get the game object's Transform
		goTransform = this.GetComponent()<Transform>;
		//get the pivot's Transform
		pivotTransform = GameObject.FindWithTag("Pivot").GetComponent<Transform>();
	}

	// Update is called once per frame
	void FixedUpdate ()
	{
		//if one of the horizontal buttons were pressed and then released
		if(Input.GetButtonUp("Horizontal"))
		{
			//if the player is at the top half
			if(goTransform.position.y>0)
			{
				topSide = true;
			}
			else //player is at the bottom half
			{
				topSide = false;
			}
		}

		//if the player is at the top half of the screen
		if(topSide)
		{
			//Right => Clockwise. Left => Counterclockwise
			motionDirection = -Input.GetAxisRaw("Horizontal");
		}
		else
		{
			//Right => Counterclockwise. Left => Clockwise
			motionDirection = Input.GetAxisRaw("Horizontal");
		}

		//rotate the player around the pivot
		goTransform.RotateAround(pivotTransform.position, Vector3.forward, motionDirection*vel);
	}
}

This second script is just like the first one: it takes the containing game object’s Transform and the Player Pivot game object Transform and the float vel. But additionally, it declares the boolean topSide, that flags whether the Player game object is at the top side of the screen; and the float motionDirection that tells if the game object should rotate clockwise or counterclockwise (lines 7 to 15). The Awake() method works exactly as the first script: it initializes the Transform member variables.

The FixedUpdate(), is where things are completely different. The first if statement checks if one of the horizontal keys were released. Case that’s true, another if statement checks the position of the Player game object, setting the topSide boolean to true, in the event that the player is at the top half of the screen, and sets it to false otherwise (lines 29 to 40).

The second if statement checks the value of topSide. If it’s value is true, pressing the right arrow key will rotate the controllable game object clockwise, storing the direction at the motionDirection float variable. Pressing left, will rotate it counterclockwise. If false, right rotates it counterclockwise and left, clockwise, also storing this result at the motionDirection variable (lines 43 through 52). Finally, the motion is applied, by calling the game object’s RotateAround() method, passing the containing game object’s Transform, the pivot’s Transform, and the motionDirection multiplied by the velocity (vel) as parameters.

In short, here’s an image to better illustrate what this script does:

The controls are inverted based on the player's position.

Still, it will be counterintuitive to many players. There is one other option: instead of inverting the controls at the top half of the screen, it’s possible to invert the motion vertically, separating the screen in right and left sides. Just replace line 32 for the following:

if(goTransform.position.x<0)

Hope that was useful for something.

Downloads

2 Comments to “Unity: Rotation Controller”

  1. Ben says:

    Thanks for your script it works great!

  2. Internet Friend says:

    Extremely thanks man !

Leave a Comment

Post Comments RSS