Rotate on 2 different axes

I am trying to create a ship controller that will rotate the ship for roll and pitch. It’s a hard concept for me as I don’t fully understand what yaw is either. But that is besides the point, I think.

The issue I am having is that if I rotate around the z axis, I can limit rotation to 30 degrees, creating roll. I can then rotate around x axis and limit the rotation to 15.

Both work fine. I think I was pulling the local angles to check for the limit.

The problem is when I rotate around both, the object begins to tumble.

Sorry I have scrapped the old code so all I have left is this explanation. I’ve tried a ton of different approaches but cannot seem to solve this.

Can anyone point me in the right direction? Links or functions to use? An explanation of how to limit the amount of pitch and roll? I don’t really want code … I want to be able to understand this kind of stuff so I can apply it to future controllers.

Thanks :slight_smile:
azmundai

Ok I think I have this working. I actually switched to rotatearound … again (i had tried it before but it had a similar problem) … it was still not resetting the rotation right until I added the slerps. Any other suggestions welcome :slight_smile:

EDIT 1 : took out some bools I didn’t need, added comments.

using UnityEngine;
using System.Collections;

public class GliderControllerTwo : MonoBehaviour {
	public float moveSpeed = 1.0f;					// Speed at which glider is moving
	private int maxSpeed = 64;						// Maximum Speed of glider (when pitching forward).
	public int glideSpeed = 32;						// Gliding Speed (neutral stick)
	public int turnSpeed = 50;						// Speed glider turns; rotates
	public float rollSpeed = 2.0f;					// Speed at which model rotates when rolling.
	public float pitchSpeed = 1.2f;					// Speed at which model rotates when pitching.
	public float altitudeChangeSpeed;				// Speed at which model is changing altitudes
	public int upSpeed = 24;						// Maximum Speed when pulling back on stick; pitching up
	private bool slerped;							// bool to prevent double slerping
	
	public float roll;								// amount to rotate on the z axis
	public float pitch;								// amount to rotate on the x axis
	
	public float rollAngle;							// amount the glider model has rotated on the z axis.
	public float pitchAngle;						// amount the glider model has rotated on the x axix.
	private float maxPitch = 0.15f;					// maximum angle to pitch model
	private float maxRoll = 0.35f;					// maximum angle to roll model.
			
	private Vector3 moveDirection = Vector3.zero;	// x y z movement amounts
	public CharacterController controller;			// the character controller
	private Transform playerModel;					// the model or parent of the model. child of object containing controller.

	// Use this for initialization
	void Start () {
		controller = GetComponent<CharacterController>();
		playerModel = transform.FindChild("PlayerModel");
	}	
	
	// Update is called once per frame
	void Update () {
		slerped = false;
		roll = pitch = 0;
		
		// Prevent Slerp when pitching or rolling
		if(Input.GetAxis("Horizontal") != 0) rolling = true;
		if(Input.GetAxis ("Vertical") != 0) pitching = true;
		
		// Roll Right when player stears right if roll angle doesnt exceed max roll
		if( (rollAngle + (Input.GetAxis("Horizontal") * rollSpeed * Time.deltaTime) < maxRoll) && Input.GetAxis("Horizontal") > 0){
				roll = Input.GetAxis("Horizontal") * rollSpeed * Time.deltaTime;
				rollAngle += Input.GetAxis("Horizontal") * rollSpeed * Time.deltaTime;
		}
				
		// Roll Left when player stears left if roll angle doesnt exceed max roll
		if( (rollAngle + (Input.GetAxis("Horizontal") * rollSpeed * Time.deltaTime) > -maxRoll) && Input.GetAxis("Horizontal") < 0){
				roll = Input.GetAxis("Horizontal") * rollSpeed * Time.deltaTime;
				rollAngle += Input.GetAxis("Horizontal") * rollSpeed * Time.deltaTime;
		}
		
		// Pitch Back when player pulls back if pitch angle doesnt exceed max pitch and slow speed
		if( (pitchAngle + (Input.GetAxis("Vertical") * pitchSpeed * Time.deltaTime) < maxPitch) && Input.GetAxis("Vertical") > 0){
				pitch = Input.GetAxis("Vertical") * pitchSpeed * Time.deltaTime;
				pitchAngle += Input.GetAxis("Vertical") * pitchSpeed * Time.deltaTime;
				altitudeChangeSpeed = Mathf.Lerp(altitudeChangeSpeed, 10, 0.1f);
				if(moveSpeed - 1 >= upSpeed)
					moveSpeed--;		
		}
		
		// Pitch Forward when player pushed forward if pitch angle doesnt exceed max pitch and increase speed
		if( (pitchAngle + (Input.GetAxis("Vertical") * pitchSpeed * Time.deltaTime) > -maxPitch) && Input.GetAxis("Vertical") < 0){
				pitch = Input.GetAxis("Vertical") * pitchSpeed * Time.deltaTime;
				pitchAngle += Input.GetAxis("Vertical") * pitchSpeed * Time.deltaTime;
				altitudeChangeSpeed = Mathf.Lerp(altitudeChangeSpeed, -10, 0.1f);
				if(moveSpeed + 1 <= maxSpeed)
					moveSpeed++;		
		}
		
		// Roll Back towards neutral when player not turning. Slerp when not pitching or rolling.
		if( Input.GetAxis("Horizontal") == 0 ){
			if( rollAngle - (0.5f * rollSpeed * Time.deltaTime) > 0 ){
				roll = 0.5f * -rollSpeed * Time.deltaTime;
				rollAngle -= 0.5f * rollSpeed * Time.deltaTime;
			} else if( rollAngle + (0.5f * rollSpeed * Time.deltaTime) < 0 ){
				roll = 0.5f * rollSpeed * Time.deltaTime;
				rollAngle += 0.5f * rollSpeed * Time.deltaTime;
			} else if(Input.GetAxis("Vertical") == 0 && Input.GetAxis("Horizontal") == 0){
				playerModel.rotation = Quaternion.Slerp (playerModel.rotation, transform.rotation, Time.deltaTime * rollSpeed);
				slerped = true;
			}
		}
		
		// Pitch Back towards neutral when player not pitching. Slerp when not pitching, rolling or slerping in horizontal.
		if( Input.GetAxis("Vertical") == 0 ){
			altitudeChangeSpeed = Mathf.Lerp(altitudeChangeSpeed, -6, 0.1f);
			
			// Ramp up to glide speed
			if(moveSpeed < glideSpeed)
				moveSpeed += moveSpeed * Time.deltaTime;									
			if(moveSpeed > glideSpeed)
				moveSpeed = glideSpeed;	
			
			if( pitchAngle - (0.5f * pitchSpeed * Time.deltaTime) > 0 ){
				pitch = 0.5f * -pitchSpeed * Time.deltaTime;
				pitchAngle -= 0.5f * pitchSpeed * Time.deltaTime;
			} else if( pitchAngle + (0.5f * pitchSpeed * Time.deltaTime) < 0 ) {
				pitch = 0.5f * pitchSpeed * Time.deltaTime;
				pitchAngle += 0.5f * pitchSpeed * Time.deltaTime;
			} else if (!slerped && Input.GetAxis("Vertical") == 0 && Input.GetAxis("Horizontal") == 0)
				playerModel.rotation = Quaternion.Slerp (playerModel.rotation, transform.rotation, Time.deltaTime * rollSpeed);
		}
		
		// set move direction from speeds
		moveDirection = new Vector3( 0, altitudeChangeSpeed, moveSpeed );
		
		// roll and pitch child.
		playerModel.RotateAroundLocal(Vector3.forward, -roll);
		playerModel.RotateAroundLocal(Vector3.right, -pitch);
		
		//transform direction
		moveDirection = transform.TransformDirection(moveDirection);
		
		// rotate transform when turning
		transform.Rotate(0 , Input.GetAxis("Horizontal") * turnSpeed * Time.deltaTime, 0, 0);
		
		// move controller
		controller.Move(moveDirection * Time.deltaTime);
	}
}