- Home /
Banking an object in relation to its turn
Hi,
I have a script (mouse look) that I have altered to achieve the movement in the game I am developing but I cannot get the object to bank when I turn. Ideally I would like the object to tilt up to say 15 degrees and when the controller returns to central have then character follow suit. The code I have rotates the character through 360 degrees with a camera that follows behind. The problem I have is that by using the turn angle I cannot return to up right until I am facing the original direction again as the tilt is out of kilter...
Code below:
var keyboardControls : boolean = true; var sensitivityX : float = 15; var sensitivityY : float = 15;
var minimumX : float = -360;
var maximumX : float = 360;
var minimumY : float = -30;
var maximumY : float = 30;
var rotationZ : float = 0;
var rotationY : float = 0;
var rotationAY : float = 0;
private var originalRotation : Quaternion;
function Update () {
if (keyboardControls) {
rotationZ += -Input.GetAxis("Mouse X");
rotationY = ClampAngleY (rotationZ, minimumY, maximumY);
rotationAY += Input.GetAxis("Mouse X") * maximumY;
}
else {
rotationZ += -Input.acceleration.y * sensitivityX;
rotationZ = ClampAngle (rotationZ, minimumX, maximumX);
rotationAY += Input.acceleration.y * maximumY;
}
var target = Quaternion.Euler( 0, rotationAY, rotationY);
transform.rotation = Quaternion.Slerp(transform.rotation, target, Time.deltaTime * sensitivityY);
var xQuaternion = Quaternion.AngleAxis (rotationZ, Vector3.up);
var yQuaternion = Quaternion.AngleAxis (rotationY, Vector3.forward);
transform.localRotation = originalRotation xQuaternion yQuaternion; }
function Start () {
if (rigidbody)
rigidbody.freezeRotation = true;
originalRotation = transform.localRotation;
}
static function ClampAngle (angle : float, min : float, max : float) : float {
if (angle < -360.0)
angle += 360.0;
if (angle > 360.0)
angle -= 360.0;
return Mathf.Clamp (angle, min, max);
}
static function ClampAngleY (angle : float, min : float, max : float) : float {
if (angle < -30.0)
angle += 30.0;
if (angle > 30.0)
angle -= 30.0;
return Mathf.Clamp (angle, min, max);
}
Should I look to implement a better way to control the movement - its supposed to be a free roaming game so I thought using the mouse look to determine direction was a good way to go...
Ideas or fixes greatly welcomed...
Regards
Answer by skovacs1 · Dec 01, 2010 at 08:16 PM
The simple answer is to get how much you are turning by and then bank by some amount relative to that, returning to your original bank rotation when you are not turning any longer.
EDIT 12/02/2010: I spent some time and tested some settings. If you want to add easing in, feel free, but something like this works fairly nicely:
var keyboardControls : boolean = true; var mouseControls : boolean = false;
//The max variables are to make the rotation framerate independent. //You could alternatively do the work in FixedUpdate, //but the controls might be less responsive there.
//Tilt var maxTilt : float = 180.0f; //Degrees/second var tiltScale : float = 60.0f; //Degrees/unitInput*second var tiltRange : float = 30.0f; //Degrees private var rotX : float = 0.0f; //Degrees
//Turn var maxTurn : float = 360.0f; //Degrees/second var turnScale : float = 120.0f; //Degrees/unitInput*second var turnRange : float = 360.0f; //Degrees private var rotY : float = 0.0f; //Degrees
//Bank var maxBank : float = 90.0f; //Degrees/second var bankScale : float = 60.0f; //Degrees/unitInput*second var returnSpeed : float = 40.0f;//Degrees/second var bankRange : float = 20.0f; //Degrees private var rotZ : float = 0.0f; //Degrees
//Input private var mouseScale : float = 1.0f; //Gs of acceleration/pixel private var deltaX : float = 0.0f; //Units of input private var deltaY : float = 0.0f; //Units of input
//Start information private var originalRot : Quaternion = Quaternion.identity;
function Update () { if(keyboardControls) { deltaX = Input.GetAxis("Horizontal"); deltaY = Input.GetAxis("Vertical"); } else if(mouseControls) { deltaX = Input.GetAxis("Mouse X")*mouseScale; deltaY = Input.GetAxis("Mouse Y")*mouseScale; } else { deltaX = Input.acceleration.x; deltaY = Input.acceleration.y; }
//Bank
if(!Mathf.Approximately(deltaX, 0.0f))
rotZ = ClampAngle(rotZ-
ClampAngle(deltaX*bankScale,-maxBank,maxBank)*Time.deltaTime,
-bankRange, bankRange);
else if(rotZ > 0.0f)
rotZ = ClampAngle(rotZ-Time.deltaTime*returnSpeed,0.0f,bankRange);
else rotZ = ClampAngle(rotZ+Time.deltaTime*returnSpeed,-bankRange,0.0f);
//Turn
rotY = ClampAngle(rotY+
ClampAngle(deltaX*turnScale,-maxTurn,maxTurn)*Time.deltaTime,
-turnRange,turnRange);
//Tilt
rotX = ClampAngle(rotX-
ClampAngle(deltaY*tiltScale,-maxTilt,maxTilt)*Time.deltaTime,
-tiltRange,tiltRange);
transform.localRotation = Quaternion.Euler(rotX,rotY,rotZ)*originalRot;
}
function Start () { if (rigidbody) rigidbody.freezeRotation = true; originalRot = transform.localRotation; }
//Modified to work when you get angles outside of -/+720 static function ClampAngle (angle : float, min : float, max : float) : float { while (angle < -360.0) angle += 360.0; while (angle > 360.0) angle -= 360.0; return Mathf.Clamp(angle, min, max); }
Thanks, I'm very new (one week) into Unity3D so apologies for the hacky code ;) I will take a look at your code and see if I can work it all out - thanks. Reason for the different axes is that the game should be played landscape on the iOS/Android so I guessed that the axes should be different too :D
I would imagine that you wouldn't want the way the game reacts to be all that different. If they move the mobile device to control the gameobject's turning and tilting, would you not want the mouse controls to also control the turning and tilting? It's more of a concern with your posted code because you only set the rotationY axis with keyboard controls, meaning that your YQuaternion and Target will likely be wrong for your mobile input.
$$anonymous$$aybe I might be better off not using the mouselook script to create the turn and go back to just a keyboard control system. Therein turning left will be 1 and right -1 or vice versa. By doing so the numbers at least match the input.accelration of the handheld devices...
skovacs1, Thanks for the expert code. +100 if I could :) $$anonymous$$any many thanks
Skovacs, one more question. The movement seems a little jerky when turning is there a way to add some smoothing or interpolation to the rotY axes?
Your answer
Follow this Question
Related Questions
How to make camera position relative to a specific target. 1 Answer
How to calculate the angle of a trajectory to hit the target 1 Answer
how the ball bounces of equal in angles? 1 Answer
Trouble Understanding Vector3.Angle() Result 2 Answers
Set angle of object around arbitrary axis by slider? 1 Answer