Hi, I’m making a third person controller and I’m running into an issue where the character rotates towards the front once I release WASD keys, instead of facing the direction that it was last facing. At the same time Unity is giving me the error shown below. As you can see, the rotation of the player character handled by the method “HandleRotation()”. I’m very new to Unity and I would appreciate it very much if someone could give me any kind of help. The complete script and the tutorials I got the script from is also provided below.
Look rotation viewing vector is zero
UnityEngine.Quaternion:LookRotation (UnityEngine.Vector3)
AnimationAndMovementController:HandleRotation () (at Assets/Scripts/AnimationAndMovementController.cs:116)
AnimationAndMovementController:Update () (at Assets/Scripts/AnimationAndMovementController.cs:186)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class AnimationAndMovementController : MonoBehaviour
{
PlayerInput playerInput;
CharacterController characterController;
Animator animator;
int isWalkingHash;
int isRunningHash;
int isJumpingHash;
Vector2 currentMovementInput;
Vector3 cameraRelativeMovement;
Vector3 currentRunMovement;
bool isMovementPressed;
bool isRunPressed;
bool isJumpPressed = false;
bool isJumpAnimating = false;
private float initialJumpVelocity;
private float maxJumpHeight = 4.0f;
private float maxJumpTime = 0.75f;
private bool isJumping = false;
private float groundedGravity = -0.05f;
private float gravity = -9.8f;
private float runMultiplier = 10.0f;
private float rotationFactorPerFrame = 30.0f;
void Awake()
{
playerInput = new PlayerInput();
characterController = GetComponent<CharacterController>();
animator = GetComponent<Animator>();
isWalkingHash = Animator.StringToHash("isWalking");
isRunningHash = Animator.StringToHash("isRunning");
isJumpingHash = Animator.StringToHash("isJumping");
playerInput.CharacterControls.Move.started += OnMovementInput;
playerInput.CharacterControls.Move.canceled += OnMovementInput;
playerInput.CharacterControls.Move.performed += OnMovementInput;
playerInput.CharacterControls.Run.canceled += OnRun;
playerInput.CharacterControls.Run.started += OnRun;
playerInput.CharacterControls.Jump.started += OnJump;
playerInput.CharacterControls.Jump.canceled += OnJump;
setupJumpVariables();
}
void setupJumpVariables()
{
float timeToApex = maxJumpTime / 2;
gravity = (-2 * maxJumpHeight) / Mathf.Pow(timeToApex, 2);
initialJumpVelocity = (2 * maxJumpHeight / timeToApex);
}
void HandleJump()
{
if (!isJumping && characterController.isGrounded && isJumpPressed)
{
animator.SetBool(isJumpingHash, true);
isJumpAnimating = true;
isJumping = true;
cameraRelativeMovement.y = initialJumpVelocity * 0.5f;
currentRunMovement.y = initialJumpVelocity * 0.5f;
}
else if (!isJumpPressed && isJumping && characterController.isGrounded)
{
isJumping = false;
}
}
void OnJump(InputAction.CallbackContext context)
{
isJumpPressed = context.ReadValueAsButton();
}
void OnRun(InputAction.CallbackContext context)
{
isRunPressed = context.ReadValueAsButton();
}
void OnMovementInput(InputAction.CallbackContext context)
{
currentMovementInput = context.ReadValue<Vector2>();
Vector3 forward = transform.InverseTransformVector(Camera.main.transform.forward.normalized);
Vector3 right = transform.InverseTransformVector(Camera.main.transform.right.normalized);
forward.y = 0;
right.y = 0;
forward = forward.normalized;
right = right.normalized;
Vector3 forwardRelativeVerticalInput = currentMovementInput.y * forward;
Vector3 rightRelativeVerticalInput = currentMovementInput.x * right;
cameraRelativeMovement = forwardRelativeVerticalInput + rightRelativeVerticalInput;
currentRunMovement.x = cameraRelativeMovement.x * runMultiplier;
currentRunMovement.z = cameraRelativeMovement.z * runMultiplier;
isMovementPressed = currentMovementInput.x != 0 || currentMovementInput.y != 0;
}
void HandleRotation()
{
Vector3 targetDirection;
targetDirection.x = cameraRelativeMovement.x;
targetDirection.z = cameraRelativeMovement.z;
targetDirection.y = 0.0f;
targetDirection.Normalize();
Quaternion targetRotation = Quaternion.LookRotation(targetDirection);
Quaternion playerRotation = Quaternion.Slerp(transform.rotation, targetRotation, rotationFactorPerFrame * Time.deltaTime);
transform.rotation = playerRotation;
}
void Start()
{
}
void HandleAnimation()
{
bool isWalking = animator.GetBool(isWalkingHash);
bool isRunning = animator.GetBool(isRunningHash);
if (isMovementPressed && !isWalking)
{
animator.SetBool(isWalkingHash, true);
}
else if (!isMovementPressed && isWalking)
{
animator.SetBool(isWalkingHash, false);
}
if ((isMovementPressed && isRunPressed) && !isRunning)
{
animator.SetBool(isRunningHash, true);
}
else if (!isMovementPressed || !isRunPressed && isRunning)
{
animator.SetBool(isRunningHash, false);
}
}
void HandleGravity()
{
bool isFalling = cameraRelativeMovement.y <= 0.0f || !isJumpPressed;
float fallMultiplier = 2.0f;
if (characterController.isGrounded)
{
if (isJumpAnimating)
{
animator.SetBool(isJumpingHash, false);
isJumpAnimating = false;
}
cameraRelativeMovement.y = groundedGravity;
currentRunMovement.y = groundedGravity;
}
else if (isFalling)
{
float previousYVelocity = cameraRelativeMovement.y;
float newYVelocity = cameraRelativeMovement.y + (gravity * fallMultiplier * Time.deltaTime);
float nextYVelocity = Mathf.Max((previousYVelocity + newYVelocity) * 0.5f);
cameraRelativeMovement.y = nextYVelocity;
currentRunMovement.y = nextYVelocity;
}
else
{
float previousYVelocity = cameraRelativeMovement.y;
float newYVelocity = cameraRelativeMovement.y + (gravity * Time.deltaTime);
float nextYVelocity = (previousYVelocity + newYVelocity) * 0.5f;
cameraRelativeMovement.y = nextYVelocity;
currentRunMovement.y = nextYVelocity;
}
}
// Update is called once per frame
void Update()
{
HandleRotation();
HandleAnimation();
if (isRunPressed)
{
characterController.Move(currentRunMovement * Time.deltaTime);
Debug.Log(isRunPressed);
}
else
{
characterController.Move(cameraRelativeMovement * Time.deltaTime);
}
characterController.Move(cameraRelativeMovement * Time.deltaTime);
HandleGravity();
HandleJump();
}
void OnEnable()
{
playerInput.CharacterControls.Enable();
}
void OnDisable()
{
playerInput.CharacterControls.Disable();
}
}
Source tutorials:
How to Move Characters in Unity 3D: Animated Movement Explained [Built-In Character Controller #2]- iHeartGameDev
<
3RD PERSON CONTROLLER in Unity - Player Movement -Sebastian Graves
<