Limiting rotation of object in script

Hi

The solution to this problem is probably quite simple but it is really troubling me.

I’m trying to make my first small project in unity. It is one of those tilting labyrinth games where you try to lead a marble around a maze without it falling into a hole. I have the game board rotating but want the degree to which it can rotate to be limited so it cant flip upside down and such. I used this script which I attached to the maze playing board object.


	// The maximum angle the board can tilt
	public float MaxTiltAngle;
	Vector3 initialRotation;
	
	// Use this for initialization
	void Start () {
		// Get initial rotation
		initialRotation = this.transform.rotation.eulerAngles;
	}
	
	// Update is called once per frame
	void Update () {

		// Add torque to the gameboard based on input
		if(Input.GetKey(KeyCode.LeftArrow))
			this.rigidbody.AddTorque(0,0,1);
		if(Input.GetKey(KeyCode.RightArrow))
			this.rigidbody.AddTorque(0,0,-1);
		if(Input.GetKey(KeyCode.UpArrow))
			this.rigidbody.AddTorque(1,0,0);
		if(Input.GetKey(KeyCode.DownArrow))
			this.rigidbody.AddTorque(-1,0,0);
		
		// Get the current rotation
		Vector3 tempRotation = this.transform.rotation.eulerAngles;
		
		// Restrict rotation along x and z axes to the maximum tilt angle 
		tempRotation.x = Mathf.Clamp(tempRotation.x, initialRotation.x - MaxTiltAngle, initialRotation.x + MaxTiltAngle);
		tempRotation.z = Mathf.Clamp(tempRotation.z, initialRotation.z - MaxTiltAngle, initialRotation.z + MaxTiltAngle);	
		
		// Set the objects rotation
		this.transform.rotation = Quaternion.Euler(tempRotation);
	}

When the game plays without the tilting being restricted it works fine but when I try and clamp the angle to 20 degrees or so the game board will no longer rotate. Instead it very slowly moves around the game scene even though I fully constrained the position along all axes in the inspector.

This definitely isn’t the best way to do what you want: rigidbodies are wild and hard to control, even more when you want to restrict rotation to certain angle.

A better way would be to get the initial eulerAngles (as you’re currently doing) and control them mathematically, assigning the result to transform.eulerAngles:

// The maximum angle the board can tilt
public float MaxTiltAngle = 20.0f;
public float tiltSpeed = 30.0f; // tilting speed in degrees/second

Vector3 curRot;
float maxX;
float maxZ;
float minX;
float minZ;

void Start () {
    // Get initial rotation
    curRot = this.transform.eulerAngles;
    // calculate limit angles:
    maxX = curRot.x + MaxTiltAngle;
    maxZ = curRot.z + MaxTiltAngle;
    minX = curRot.x - MaxTiltAngle;
    minZ = curRot.z - MaxTiltAngle;
}

void Update () {
    // "rotate" the angles mathematically:
    curRot.x += Input.GetAxis("Vertical") * Time.deltaTime * tiltSpeed;
    curRot.z += Input.GetAxis("Horizontal") * Time.deltaTime * tiltSpeed;                
    // Restrict rotation along x and z axes to the limit angles:
    curRot.x = Mathf.Clamp(curRot.x, minX, maxX);
    curRot.z = Mathf.Clamp(curRot.z, minZ, maxZ);
    
    // Set the object rotation
    this.transform.eulerAngles = curRot;
}