Restrict Rotation to a range

Hi,

I’m trying to restrict the rotational movement of a game object on the x and z axis. When the game object is at the edge or the range, or exceeds it, I want the game object to begin to rotate back to its “level” position. I’m trying to make a vehicle that hoovers and that has some flexibility in rotational movement.

This is not working:

if(transform.eulerAngles.x > 30)
{
transform.Rotate(-1, 0, 0);
}
else if(transform.eulerAngles.x < -30)
{
transform.Rotate(1, 0, 0);
}

if(transform.eulerAngles.z > 30)
{
transform.Rotate(0, 0, -1);
}
else if(transform.rotation.z < -30)
{
transform.Rotate(0, 0, 1);
}

You can get unexpected effects trying to use eulerangles. The simplest solution is to keep track of your rotation in a variable and use that to restrict rotation. So you create a float called, say, trackedRotation, and add or subtract how much you’ve rotated to it as the rotation is performed.

Thanks for your reply.

Is this what you are advising?

float lastRotationX = transform.rotation.x;
float trackedRotationX = transform.rotation.x - lastRotationX;
transform.Rotate(trackedRotationX, 0, 0);

float lastRotationZ = transform.rotation.z;
float trackedRotationZ = transform.rotation.z - lastRotationZ;
transform.Rotate(0, 0, trackedRotationZ);

i tried it and it does work, but sometimes the vehicle still completely flips over.

I also tried this:

transform.Rotate(transform.rotation.x * -1, 0, 0);
transform.Rotate(0, 0, transform.rotation.z * -1);

This seems to work a little too, but still the vehicle can completely flip.

I’m trying to create a vehicle that appears to hover, it rotates on the x and z axis so it can go up and down hills. But when the vehicle’s x and or z rotation is not level (0) then I want it to rotate back to 0. So if the vehicle drives up a sloop and get’s air, jumps, it levels off, x and z move back to 0. And the vehicle never flips over.

Thanks for you help.

You’re on the right track, but a little bit off. Here’s how I’m doing a similar concept that prevents rotating something (a camera, in this case) more than 90 degrees in either direction:

    private float cameraPitch = 0f;

    private void TiltCamera(float tiltAxis)
    {
        cameraPitch += tiltAxis;
        if ((cameraPitch < 90)  (cameraPitch > -90))
            cameraInUse.transform.Rotate(Vector3.right * tiltAxis);
        else
            cameraPitch -= tiltAxis;
    }

You’d probably want to change Vector3.right to Vector3.up, but other than that, it should work as expected, or at least, works as expected on my camera object.

Thank you for that. What calls the TiltCamera method? My vehicles x and z rotation is being affected/changed by the physics when driving up steep terrain. Any suggestions on how I would intercept when the vehicle is rotating?

Cheers.

I hadn’t really thought of the physics aspect, my method is more for restricting the pitch while setting it manually…Sorry, bad solution.

Try this, instead:
Select your hoverboard, then go to the Component menu=> Scripts=>Rotation Constraint
That script will show you the proper way to do it, since I’m failing so spectacularly.

Thank you for your help Dameon. I’m using Unity 4 and I don’t see a Rotation Constraint in the Scripts menu location. I only see scripts I created in the Scripts drop down. I Googled “Rotation Constraint” and couldn’t find help. Any ideas where it could be?

I’m on 4.3.2, you may need to import it? Not sure, I can post it tomorrow when I’m at my desk again.

It’s under standard assets(mobile) on the imports, but here’s the script

//////////////////////////////////////////////////////////////
// RotationConstraint.js
// Penelope iPhone Tutorial
//
// RotationConstraint constrains the relative rotation of a 
// Transform. You select the constraint axis in the editor and 
// specify a min and max amount of rotation that is allowed 
// from the default rotation
//////////////////////////////////////////////////////////////

enum ConstraintAxis
{
	X = 0,
	Y,
	Z
}

public var axis : ConstraintAxis; 			// Rotation around this axis is constrained
public var min : float;						// Relative value in degrees
public var max : float;						// Relative value in degrees
private var thisTransform : Transform;
private var rotateAround : Vector3;
private var minQuaternion : Quaternion;
private var maxQuaternion : Quaternion;
private var range : float;

function Start()
{
	thisTransform = transform;
	
	// Set the axis that we will rotate around
	switch ( axis )
	{
		case ConstraintAxis.X:
			rotateAround = Vector3.right;
			break;
			
		case ConstraintAxis.Y:
			rotateAround = Vector3.up;
			break;
			
		case ConstraintAxis.Z:
			rotateAround = Vector3.forward;
			break;
	}
	
	// Set the min and max rotations in quaternion space
	var axisRotation = Quaternion.AngleAxis( thisTransform.localRotation.eulerAngles[ axis ], rotateAround );
	minQuaternion = axisRotation * Quaternion.AngleAxis( min, rotateAround );
	maxQuaternion = axisRotation * Quaternion.AngleAxis( max, rotateAround );
	range = max - min;
}

// We use LateUpdate to grab the rotation from the Transform after all Updates from
// other scripts have occured
function LateUpdate() 
{
	// We use quaternions here, so we don't have to adjust for euler angle range [ 0, 360 ]
	var localRotation = thisTransform.localRotation;
	var axisRotation = Quaternion.AngleAxis( localRotation.eulerAngles[ axis ], rotateAround );
	var angleFromMin = Quaternion.Angle( axisRotation, minQuaternion );
	var angleFromMax = Quaternion.Angle( axisRotation, maxQuaternion );
		
	if ( angleFromMin <= range  angleFromMax <= range )
		return; // within range
	else
	{		
		// Let's keep the current rotations around other axes and only
		// correct the axis that has fallen out of range.
		var euler = localRotation.eulerAngles;			
		if ( angleFromMin > angleFromMax )
			euler[ axis ] = maxQuaternion.eulerAngles[ axis ];
		else
			euler[ axis ] = minQuaternion.eulerAngles[ axis ];

		thisTransform.localEulerAngles = euler;		
	}
}
2 Likes

Thank you for that!

That seems to work. I’m going to reverse engineer the script.