Clamp Camera X rotation --- Popping problem

Thinking I could go to another script while I get some insight on another problem, I tried working on my camera again… Problem here, is that whenever I pass the 0 mark for rotations my camera -POPS-. What I mean is, I’ll be looking at… 20 degrees to the right, if I rotate my character past the 0 mark, I’ll then be looking at 340 degrees (20 degrees to the left). I’ve looked at the mouselook script, I’ve looked at modifying the script I have now, but I get the same result. A popping effect after passing over 0 degrees.

var target : Transform;

var targetHeight = 2.0;
var distance = 5.0;

var maxDistance = 20;
var minDistance = 2.5;

var xSpeed = 250.0;
var ySpeed = 120.0;

var yMinLimit = -20;
var yMaxLimit = 80;

var xMinLimit = -40;
var xMaxLimit = 40;

var zoomRate = 20;

var rotationDampening = 3.0;

private var x = 0.0;
private var y = 0.0;
private var originalRotation : Quaternion;


@script AddComponentMenu("Camera-Control/WoW Camera")

function Start () {
    var angles = transform.eulerAngles;
    x = angles.y;
    y = angles.x;

   // Make the rigid body not change rotation
      if (rigidbody)
      rigidbody.freezeRotation = true;
}

function Update () {
   if(!target)
      return;
   
   // If either mouse buttons are down, let them govern camera position
   if (Input.GetMouseButton(0) || Input.GetMouseButton(1))
   {
   x += Input.GetAxis("Mouse X") * xSpeed * 0.02;
   y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02;
   
   //Make it so you cannot rotate past the character's natural head movement. This will make shooting
   //Seem more realistic, and you won't be able to shoot from your butt.
    //x = Mathf.Clamp(x, (target.eulerAngles.y + xMinLimit), (target.eulerAngles.y + xMaxLimit));
	//x = ClampAngle(x, xMinLimit, xMaxLimit);
	
   
   // otherwise, ease behind the target if any of the directional keys are pressed
   } else if(Input.GetAxis("Vertical") || Input.GetAxis("Horizontal")) {
      var targetRotationAngle = target.eulerAngles.y;
      var currentRotationAngle = transform.eulerAngles.y;
      x = Mathf.LerpAngle(currentRotationAngle, targetRotationAngle, rotationDampening * Time.deltaTime);
   }
   
   distance -= (Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime) * zoomRate * Mathf.Abs(distance);
   distance = Mathf.Clamp(distance, minDistance, maxDistance);
   
   y = ClampAngle(y, yMinLimit, yMaxLimit);

   
   var rotation:Quaternion = Quaternion.Euler(y, x, 0);
   var position = target.position - (rotation * Vector3.forward * distance + Vector3(0,-targetHeight,0));
   
   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);
} 

static function ClampAngleX (angle : float, min : float, max : float) {
   if (angle < -360)
      angle = -360;
   if (angle > 360)
      angle = 360;
   return Mathf.Clamp (angle, min, max);
}

Don’t worry about ClampAngleX, I thought I could change some variables around to fix the popping problem.

Anyways note the two lines:

//x = Mathf.Clamp(x, (target.eulerAngles.y + xMinLimit), (target.eulerAngles.y + xMaxLimit));
//x = ClampAngle(x, xMinLimit, xMaxLimit);

The first line allows me to stay within an 80 degree area. However when I use that line, my camera pops at 0 degrees. I’m rotating my character, btw.

The second line clamps the degrees correctly, I get no popping, but I can only see things within that 80 degree area. Which means I can’t see where I’m going if I need to run in the opposite direction.

I need to solve the popping problem, because if I don’t have a clamp on rotating the camera from side to side, my character can shoot from their butt… Which is wrong.

Any clue on how to keep the camera behind the character within that 80 degree box, and keep it from popping whenever it passes the 0 degree threshold?

I’m not quite sure what you mean by the zero degree point when the camera pops. Is it when the camera is directly behind the player or when the player’s rotation is 0º in world space?

Whenever I’m dragging the camera around (planning on it for no drag after this problem’s fixed***), and my player’s rotation goes past 0º in world-space, the camera pops.

I can hold the mouse button down to drag the camera, keep the button down, without moving the mouse, and rotate all of the way around. The camera will stay at the minimum/maximum the entire time that I’m rotating. But as soon as I pass over that threshold (The player rotates past 0º in world-space) It will “pop”. It’s quite an obvious pop too, as it completely flips the camera around. Feel free to try the script with an FPS walker with the camera outside of the character. You’ll notice it pop from one degree of rotation to the opposite (-20 to 40 for example).

What will happen is, whenever I pass the threshold, I’ll go to the minimum/maximum. If I rotate left, it will go to the minimum when I pass 0 degrees and vice versa to the right.

There’s got to be a piece of code that I can slip in to prevent it from flipping my rotation so radically. Either that, or a way to restructure it.

***Why do I want no drag after it’s fixed? Because I’m finding that dragging in order to aim my “shooter” is a pain in the butt. And if I find it a pain in the butt, my players are going to find it a pain in the butt.

I think this might be a problem with an equality comparison in the eulerAngles property. Try using this function to get the rotation around the Y axis:-

function GetYAngle() {
	var fwd = transform.forward;
	return Mathf.Repeat(360 + Mathf.Atan2(fwd.x, fwd.z) * Mathf.Rad2Deg, 360);
}

How do I set that up with the code that I already have? It looks like it works, but I’m not sure where I would need to put it (in the Update?.. ^^;; ) I’m not talking about the function declaration (That goes somewhere at the bottom… Probably near the depths of hell XP), I’m talking about where to put “GetYAngle()”

I’m going to have to re-think my aiming mechanism a bit… I discovered that zooming my camera moves my “Bubble Blower” far away from where my character should be shooting it. which means I may not need my X-clamping for my camera. Which now means I need to look at the 3rd person shooter example to see if I can’t do something similar to that (figuring out a way to twist the head within reasonable limits).