There are a few basic concepts on how cameras should work. You can “rotate” them around things, or you can calculate the rotation, then get the position based on the rotation, or you can calculate the rotation then force the position. All are valid methods if used in the correct context.
On almost all of the cameras I create now, they are controlled by the thing that they are to be looking at. I rarely use an external camera controller. I found them to be buggy as Unity does not always follow the same path for running scripts. This causes jitteryness that is highly undesirable.
I also use the method of calculation of the rotation, then translation on the distance. This gives me some advantages. 1) It is incredibly easy to understand, and 2) I can use the two points in a Line or Raycast to check for obstruction.
The basics are:
Set the camera’s rotation according to the X and Y inputs.
x += Input.GetAxis("Mouse X") * xSpeed * 0.02;
y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02;
y = ClampAngle(y, yMinLimit, yMaxLimit);
var rotation = Quaternion.Euler(y, x, 0);
Camera.main.transform.rotation = rotation;
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);
}
Set the position of the camera to the target
Camera.main.transform.position = transform.position;
Run calculations for distance (this would be where you would use a linecast from the point the camera is now, to the point where it should be)
NOTE: In calculation for Raycasts/Linecasts always use the distance - 1. This will allow you to set the distance to hit - 1 if you happen to hit something.
Lastly, just move the camera the distance needed.
Camera.main.transform.Translate(Vector3.back * distance);