Hey guys,
As the title says, I am trying to modify the MouseOrbit script supplied with Unity so that it also clamps the X axis. The desired result is that the camera will not rotate post a min and max variable (for my example i use 40 and -40 degrees) of the object it is watching.
Below is an image illustrating what the desired result is. This is designed for a tank script. The turret looks at a ray cast via the camera and uses Quaternion.Lerp to look at the ray hit point. For this specific tank I wish for the turret to only be able to shoot in front of the vehicle, that is why I have decided to try edit the MouseOrbit script to achieve this.
The turret shouldn’t be able to look past the min and max angles illustrated above.
Now I have managed to achieve this mostly through the addition of these lines to the original MouseOrbit.js script
var targetY = targetRotation.localEulerAngles.y;
var newXMinLimit = targetY + xMinLimit;
var newXMaxLimit = targetY + xMaxLimit;
x = ClampAngle(x, newXMinLimit, newXMaxLimit);
The whole script looks as follows for those who are interested
var target : Transform;
var targetRotation : Transform;
var distance = 10.0;
var xSpeed = 250.0;
var ySpeed = 120.0;
var yMinLimit = -20;
var yMaxLimit = 80;
var xMinLimit = -40;
var xMaxLimit = 40;
private var x = 0.0;
private var y = 0.0;
function Start () {
var angles = target.transform.eulerAngles;
x = angles.y;
y = angles.x;
// Make the rigid body not change rotation
if (rigidbody) {
rigidbody.freezeRotation = true;
}
}
function LateUpdate () {
if (target) {
x += Input.GetAxis("Mouse X") * xSpeed * 0.02;
y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02;
var targetY = targetRotation.localEulerAngles.y;
var newXMinLimit = targetY + xMinLimit;
var newXMaxLimit = targetY + xMaxLimit;
y = ClampAngle(y, yMinLimit, yMaxLimit);
x = ClampAngle(x, newXMinLimit, newXMaxLimit);
var rotation = Quaternion.Euler(y, x, 0);
var position = rotation * Vector3(0.0, 0.0, -distance) + target.position;
transform.rotation = rotation;
transform.position = position;
}
}
static function ClampAngle (angle : float, min : float, max : float) {
if (angle < -360)
angle += 360;
if (angle > 360)
angle -= 360;
return Mathf.Clamp (angle, min, max);
}
Now the problem I have run into is when the forward direction of the base reaches between 320 to 0 to 40 degrees. The camera jumps 40 degrees to the right or left when the base enters these angles. I checked into how Mathf.Clamp works and basically it checks whether the camera angle is <= the min or >= the max and sets it to it if it is true.
Basically the following:
if (x >= max) {
x = max
} else if (x <= min) {
x = min
}
Now when the base enters the angles between 320 and 40, these are what those min and max angles are:
Base direction = 39 : max = 79 : min = 359;
Base direction = 20 : max = 60 : min = 340;
Base direction = 0 : max = 40 : min = 320;
Base direction = 340 : max = 20 : min = 300;
Base direction = 321 : max = 1 : min = 281;
Now if you place those values into the above if statement you can see why it jumps. Where, in angle terms, 39 degrees should be greater than 359 for the example I used, but the if statement obviously records the latter. same with 321 degrees should be less than 1 for the if statement to work.
I hope I am making sense. I have tried to work around this but I am completely stumped as to how I would fix this.
I don’t believe in posting questions that could have been solved through proper searching, but this time I really haven’t been able to solve this on my own.
Can anyone show me how I would get around this? It would be much appreciated.