I am trying to program a third person character such that when a direction key, eg. D is pressed, if the character is currently facing same direction as camera, Right Quarter Turn animation is played, if it is facing the camera, Left Quarter Turn is played, similar to GTA V. But I am having trouble getting angles between camera and player in the Y plane. I tried this into the player control script:
void Right()
{
Vector3 pVec = Vector3.ProjectOnPlane(transform.forward, Vector3.up);
Vector3 cVec = Vector3.ProjectOnPlane(mainCam.transform.forward, Vector3.up);
print(cVec);
float angle = Vector3.Angle(pVec, cVec);
print(angle);
if(angle >= 345 && angle <= 15)
{
animator.Play("StandQuarterTurnRight");
}
else if(angle >= 255 && angle <= 285)
{
animator.Play("StandHalfTurnRight");
}
else if(angle >= 165 && angle <= 195)
{
animator.Play("StandQuarterTurnLeft");
}
else if(angle >=75 && angle <= 105)
{
float forw = Input.GetAxis("Horizontal");
if (forw > 0.5f && !Input.GetKey(KeyCode.LeftShift)) forw = 0.5f;
else if (forw < -0.5f && !Input.GetKey(KeyCode.LeftShift)) forw = -0.5f;
animator.SetFloat("Speed", forw);
}
}
But it is not working, I get wrong angles. I is giving me 90 when character faces right or left of camera forward, and wrong angles for others and it doesn't give 180+ at all, what am I doing wrong? Is there a better way to achieve what I am trying?
I would transform the viewdirection of the camera into the coordinate system of your character. Then it is very easy so see where you want him to turn or move.
Assuming your camera's rotation is at mainCam.transform.rotation, you can use this code:
float target_angle = 90.0f; // assuming want to turn 'right'.
// direction of camera, in worldspace.
Vector3 cam_dir = mainCam.transform.forward;
// now transform to a direction vector in character's local space.
cam_dir = transform.InverseTransformDirection(cam_dir);
// ignore y part, take X/Z to get the angle.
// 0 degrees is forward, 90 deg is toward positive X, so normally right.
float cam_angle = Mathf.Atan2(cam_dir.x,cam_dir.z)*Mathf.Rad2Deg;
// angle we need to turn
float turn_angle = target_angle - cam_angle;
// [.....] do it now.
Using the InverseTransformXxx() function is often very helpful if trying to think in some character's local view. You could also transform the camera's position into the character's space by using char.transform.InverseTransformPoint(mainCam.transform.position) and use that for some reference.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With