So i’m working on a game with third person shooter type controls. It has mouselook, wasd keys move based on camera pointing. But since the character is on the ground, they can only move on the XZ plane, and only rotate around the Y axis. In theory anyway
I wrote some code for slow turning, it gradually rotates the target towards the direction they’re moving. (not necessarily the direction the camera is facing, but often)
It mostly works to limiit the character’s rotation, but sometimes, for very large rotations (like if i try to move in the opposite direction the character is facing) it screws up, and in order to point at the target, my character gets flipped through several other axes to find a shorter path than spinning around Y.
I wrote most of my code, but the solution for finding the direction of rotation, i may have found on a random unity answers post. And therefore don’t fully understand it.
It’s worth noting, the character is using a characterController. Though i’m not sure it has any special functions for this. Most notably though, there is no rigidbody, and so i can’t just freeze rotation on the undesired axes
The relevant part of my code:
//Code for rotating towards direction
Quaternion newTargetRot = (Quaternion.FromToRotation(transform.forward, VectorTools.Flatten(controller.velocity)) * body.transform.rotation);
if (newTargetRot != targetTurningRotation)
{
Shortcuts.ClearConsole();
targetTurningRotation = newTargetRot;
Vector3 fwdCurrent = body.transform.rotation * Vector3.forward;
Vector3 fwdTarget = targetTurningRotation * Vector3.forward;
float angleCurrent = Mathf.Atan2(fwdCurrent.x, fwdCurrent.z) * Mathf.Rad2Deg;
float angleTarget = Mathf.Atan2(fwdTarget.x, fwdTarget.z) * Mathf.Rad2Deg;
float diff = Mathf.DeltaAngle(angleCurrent, angleTarget);
if (diff < 0f)
{
targetTurningDirection = -1;
}
else
{
targetTurningDirection = 1;
}
Debug.Log("Calculating! "+targetTurningDirection);
turningAngleToTarget = Mathf.Abs(diff);
}
else
{
turningAngleToTarget = Quaternion.Angle(targetTurningRotation, body.transform.rotation);
}
if (turningAngleToTarget < angularSpeedPerFixedUpdate)
{
body.transform.rotation = targetTurningRotation;
anim.SetFloat("Direction", 0f);
}
else
{
float fraction = angularSpeedPerFixedUpdate / turningAngleToTarget;
Debug.Log("Turning: " + fraction);
anim.SetFloat("Direction", (turningAngleToTarget / 180f));
body.transform.rotation = Quaternion.Lerp(body.transform.rotation, targetTurningRotation, fraction);
}
I think the main problem here is that Quaternion.Lerp is too good at finding the shortest path, and that path is often not only around my desired axes. So i probably need to replace the lerp with some custom lerping. but how?
What can i do to fix this?