- Home /
Slowly rotating camera to face same direction as player
Okay, so this will take a little explaining.
In my current project, I have an animated character that has a camera placed slightly behind and to the right of him, much like the camera placement in Resident Evil 4 and 5. When the player is either stationary or walking slowly forward (not running), the camera can move within certain bounds in both the horizontal and vertical directions based on the movement of the mouse, allowing the player to scan the general area in front of and around the character. However, I restrict the camera to face dead forward whenever the character runs or walks backwards. This works just fine, but my problem is that the camera immediately snaps into place, which is sudden and disorienting.
I have tried multiple approaches to making the camera glide smoothly into place, using all the Quaternion functions I could think of: Slerp, Lerp, RotateTowards, LookRotation + Slerp, etc.
If someone could help me find the code that would allow for the camera to move nicely and easily into alignment with the characters rotation, I would be greatly appreciative. I have tried to find something that was already asked that would help me with this, but I can't seem to find anything that works.
The code I have is as follows:
rotationY += Input.GetAxis ("Mouse Y") * 3.0f;
rotationY = Mathf.Clamp (rotationY, -20.0f, 15.0f);
if (anim.GetFloat ("Speed") < 2.0f && anim.GetFloat ("Speed") >= 0.0f)
{
rotationX += Input.GetAxis ("Mouse X") * 3.0f;
rotationX = Mathf.Clamp (rotationX, -45.0f, 45.0f);
}
else
{
rotationX = Quaternion.Slerp (Camera.main.transform.localRotation, transform.rotation, 1.0f * Time.deltaTime).x;
//This code just causes the camera to snap dead forwards, I don't understand why
}
UPDATE: Thanks to jenci1990, I figured out the problem. The following code is my final solution:
if (anim.GetFloat ("Speed") < 2.0f && anim.GetFloat ("Speed") >= 0.0f)
{
if (rotationX > 45.0f)
rotationX = rotationX - 360.0f;
rotationX += Input.GetAxis ("Mouse X") * 3.0f;
rotationX = Mathf.Clamp (rotationX, -45.0f, 45.0f);
}
else
{
float camX = Camera.main.transform.localEulerAngles.y;
float rotX = transform.forward.y;
rotationX = Mathf.LerpAngle(camX, rotX, 3.0f * Time.deltaTime);
}
Answer by jenci1990 · Dec 01, 2014 at 06:33 PM
try this:
rotationX = Vector3.Lerp(Camera.main.transform.localEulerAngles, transform.eulerAngles, 1.0f * Time.deltaTime).x;
Hmmm...it does help, but it presents another problem. When I have the camera rotated to the right of the character (positive y rotation), it does glide smoothly into place when I start running; however, when I have the camera rotated to the left (negative y rotation), it causes the camera to do a full 360 spin to lock itself into place. The camera will only rotate counter-clockwise.
Send the full rotation controll script, because i don't know where is the problem.
void Start()
{
controller = (!controller ? GetComponent<CharacterController> () : controller);
anim = (!anim ? GetComponent<Animator> () : anim);
rotationY = 0.0f;
rotationX = 0.0f;
Screen.lockCursor = true;
Screen.showCursor = false;
}
void Update()
{
transform.rotation = forward;
float vertical = Input.GetAxis ("Vertical");
float horizontal = Input.GetAxis ("Horizontal");
bool isRunning = vertical > 0.0f && Input.Get$$anonymous$$ey ($$anonymous$$eyCode.LeftShift);
Animate (vertical, horizontal, isRunning);
transform.Rotate (0.0f, horizontal * (isRunning ? 105.0f : 65.0f) * Time.deltaTime, 0.0f);
forward = transform.rotation;
ApplyGravity ();
rotationY += Input.GetAxis ("$$anonymous$$ouse Y") * 3.0f;
rotationY = $$anonymous$$athf.Clamp (rotationY, -20.0f, 15.0f);
if (anim.GetFloat ("Speed") < 2.0f && anim.GetFloat ("Speed") >= 0.0f)
{
rotationX += Input.GetAxis ("$$anonymous$$ouse X") * 3.0f;
rotationX = $$anonymous$$athf.Clamp (rotationX, -45.0f, 45.0f);
}
else
{
rotationX = Vector3.Lerp (Camera.main.transform.localEulerAngles, transform.forward, 3.0f * Time.deltaTime).y;
}
}
void LateUpdate()
{
Camera.main.transform.localEulerAngles = new Vector3(-rotationY,
rotationX, 0.0F);
}
The rotationX and rotationY values correspond to the X and Y $$anonymous$$ouse axes, not the euler rotation values x and y.
Replace this line:
rotationX = Vector3.Lerp (Camera.main.transform.localEulerAngles, transform.forward, 3.0f * Time.deltaTime).y;
for this :
float camX = Camera.main.transform.localEulerAngles.x;
float rotX = transform.forward.x;
rotationX = $$anonymous$$athf.LerpAngle(camX, rotX, 3.0f * Time.deltaTime);
Fantastic! Thank you very much. Only had to make some small adjustments to deal with the value of rotationX being changed from a negative angle to a positive angle around the 340 degree area. Here is the final code:
if (anim.GetFloat ("Speed") < 2.0f && anim.GetFloat ("Speed") >= 0.0f)
{
if (rotationX > 45.0f)
rotationX = rotationX - 360.0f;
rotationX += Input.GetAxis ("$$anonymous$$ouse X") * 3.0f;
rotationX = $$anonymous$$athf.Clamp (rotationX, -45.0f, 45.0f);
}
else
{
float camX = Camera.main.transform.localEulerAngles.y;
float rotX = transform.forward.y;
rotationX = $$anonymous$$athf.LerpAngle(camX, rotX, 3.0f * Time.deltaTime);
}
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Viewmodel/camera rotation when moving 1 Answer
How to smoothly rotate camera around an object with touch 1 Answer
Aiming, Camera Orbit 0 Answers