Been following this guide https://youtu.be/bXNFxQpp2qk?t=1280 for Character Controller. This got me getting basic movement working and at time 21:20 he creates a way to rotate the player.
https://youtu.be/b0AQg5ZTpac and this video for the player facing the mouse position. At the 7:15 mark she explains how to get the mousePosition in which I stored it in positionToLookAt
I want my character's rotation to be done with the mouse and have a field of view like here: https://youtu.be/rQG9aUWarwE
Been trying to to get it so that the player is facing the direction of the mouse position, but haven't been getting the result. With here showing https://imgur.com/gallery/mPPWogi the video results and my PlayerInputs.
Some peers mentioned replacing
Quaternion targetRotation = Quaternion.LookRotation(positionToLookAt);
by
Quaternion targetRotation = Quaternion.LookRotation(positionToLookAt - transform.position);
But it doesn't work and produced the same results in the imgur.
Can anyone help me out here? I'm stuck and I have no idea how to make this character look at the mouse instead.
here's the snippet of the method
void handleRotation()
{
Vector3 positionToLookAt;
// get mouse position
Vector2 mousePosition = playerInput.CharacterControls.MousePosition.ReadValue<Vector2>();
mousePosition = Camera.main.ScreenToWorldPoint(mousePosition);
// insert mouse position to looking position
positionToLookAt.x = currentMovement.x;
//positionToLookAt.x = mousePosition.x;
positionToLookAt.y = 0.0f;
positionToLookAt.z = currentMovement.z;
//positionToLookAt.z = mousePosition.y;
Quaternion currentRotation = transform.rotation;
if (isMovementPressed)
{
Quaternion targetRotation = Quaternion.LookRotation(positionToLookAt);
transform.rotation = Quaternion.Slerp(currentRotation, targetRotation, rotationFactorPerFrame * Time.deltaTime);
}
}
And if anyone wants my full code, here.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class AnimationAndMovementController : MonoBehaviour
{
PlayerInput playerInput;
UnityEngine.CharacterController characterController;
Animator animator;
int isWalkingHash;
int isRunningHash;
Vector2 currentMovementInput;
Vector3 currentMovement;
Vector3 currentRunMovement;
bool isMovementPressed;
bool isRunPressed;
float rotationFactorPerFrame = 15.0f;
float runMultiplier = 3.0f;
//Debug.Log(context.ReadValue<Vector2>());
void Start()
{
}
void Awake()
{
playerInput = new PlayerInput();
characterController = GetComponent<UnityEngine.CharacterController>();
animator = GetComponent<Animator>();
isWalkingHash = Animator.StringToHash("isWalking");
isRunningHash = Animator.StringToHash("isRunning");
playerInput.CharacterControls.Move.started += onMovementInput;
playerInput.CharacterControls.Move.canceled += onMovementInput;
playerInput.CharacterControls.Move.performed += onMovementInput;
playerInput.CharacterControls.Run.started += onRun;
playerInput.CharacterControls.Run.canceled += onRun;
}
void onRun(InputAction.CallbackContext context)
{
isRunPressed = context.ReadValueAsButton();
}
void onMovementInput (InputAction.CallbackContext context)
{
currentMovementInput = context.ReadValue<Vector2>();
currentMovement.x = currentMovementInput.x;
currentMovement.z = currentMovementInput.y;
currentRunMovement.x = currentMovementInput.x * runMultiplier;
currentRunMovement.z = currentMovementInput.y * runMultiplier;
isMovementPressed = currentMovementInput.x != 0 || currentMovementInput.y != 0;
}
void handleRotation()
{
Vector3 positionToLookAt;
Vector2 mousePosition = playerInput.CharacterControls.MousePosition.ReadValue<Vector2>();
mousePosition = Camera.main.ScreenToWorldPoint(mousePosition);
positionToLookAt.x = currentMovement.x;
//positionToLookAt.x = mousePosition.x;
positionToLookAt.y = 0.0f;
positionToLookAt.z = currentMovement.z;
//positionToLookAt.z = mousePosition.y;
Quaternion currentRotation = transform.rotation;
if (isMovementPressed)
{
Quaternion targetRotation = Quaternion.LookRotation(positionToLookAt);
transform.rotation = Quaternion.Slerp(currentRotation, targetRotation, rotationFactorPerFrame * Time.deltaTime);
}
}
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);
}
else if ((isMovementPressed && !isRunPressed) && isRunning)
{
animator.SetBool(isRunningHash, false);
}
}
void handleGravity()
{
if (characterController.isGrounded) {
float groundedGravity = -0.05f;
currentMovement.y = groundedGravity;
currentRunMovement.y = groundedGravity;
} else {
float gravity = -9.8f;
currentMovement.y = gravity;
currentRunMovement.y = gravity;
}
}
// Update is called once per frame
void Update()
{
handleRotation();
handleAnimation();
handleGravity();
if (isRunPressed) {
characterController.Move(currentRunMovement * Time.deltaTime);
}
else {
characterController.Move(currentMovement * Time.deltaTime);
}
}
void OnEnable()
{
playerInput.CharacterControls.Enable();
}
void OnDisable()
{
playerInput.CharacterControls.Disable();
}
}
EDIT
Updated full code and handleRotation() is where Rotation is being handled:
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;
Camera _camera;
Vector2 currentMovementInput;
Vector3 currentMovement;
Vector3 currentRunMovement;
bool isMovementPressed;
bool isRunPressed;
//float rotationFactorPerFrame = 15.0f;
float runMultiplier = 3.0f;
// Start is called before the first frame update
void Start()
{
_camera = Camera.main;
}
void Awake()
{
playerInput = new PlayerInput();
characterController = GetComponent<CharacterController>();
animator = GetComponent<Animator>();
isWalkingHash = Animator.StringToHash("isWalking");
isRunningHash = Animator.StringToHash("isRunning");
playerInput.CharacterControls.Move.started += onMovementInput;
playerInput.CharacterControls.Move.canceled += onMovementInput;
playerInput.CharacterControls.Move.performed += onMovementInput;
playerInput.CharacterControls.Run.started += onRun;
playerInput.CharacterControls.Run.canceled += onRun;
}
void onRun(InputAction.CallbackContext context)
{
isRunPressed = context.ReadValueAsButton();
}
void onMovementInput(InputAction.CallbackContext context)
{
currentMovementInput = context.ReadValue<Vector2>();
currentMovement.x = currentMovementInput.x;
currentMovement.z = currentMovementInput.y;
currentRunMovement.x = currentMovementInput.x * runMultiplier;
currentRunMovement.z = currentMovementInput.y * runMultiplier;
isMovementPressed = currentMovementInput.x != 0 || currentMovementInput.y != 0;
}
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);
}
else if ((isMovementPressed && !isRunPressed) && isRunning)
{
animator.SetBool(isRunningHash, false);
}
}
void handleGravity()
{
if (characterController.isGrounded)
{
float groundedGravity = -0.05f;
currentMovement.y = groundedGravity;
currentRunMovement.y = groundedGravity;
}
else
{
float gravity = -9.8f;
currentMovement.y = gravity;
currentRunMovement.y = gravity;
}
}
void handleRotation()
{
// We're getting a Vector2, whereas we will need a Vector3
// Get a z value based on camera, and include it in a Vector3
var mousePosition = playerInput.CharacterControls.MousePosition.ReadValue<Vector2>();
var mousePositionZ = _camera.farClipPlane * .5f;
var mouseViewportPosition = _camera.ScreenToWorldPoint(new Vector3(mousePosition.x, mousePosition.y, mousePositionZ));
// Do the same with the object's position
var positionOnViewport = Camera.main.WorldToViewportPoint(transform.position);
// Get the angle between the points
var angle = AngleBetweenTwoPoints(positionOnViewport, mouseViewportPosition);
// Apply the angle as the rotation of the object
transform.rotation = Quaternion.Euler(new Vector3(0f, -angle, 0f));
}
float AngleBetweenTwoPoints(Vector3 a, Vector3 b)
{
return Mathf.Atan2(b.y - a.y, b.x - a.x) * Mathf.Rad2Deg;
}
// Update is called once per frame
void Update()
{
handleRotation();
handleAnimation();
handleGravity();
if (isRunPressed)
{
characterController.Move(currentRunMovement * Time.deltaTime);
}
else
{
characterController.Move(currentMovement * Time.deltaTime);
}
}
void OnEnable()
{
playerInput.CharacterControls.Enable();
}
void OnDisable()
{
playerInput.CharacterControls.Disable();
}
}
EDIT 2: with current iteration
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;
Camera _camera;
Vector2 currentMovementInput;
Vector3 currentMovement;
Vector3 currentRunMovement;
bool isMovementPressed;
bool isRunPressed;
float rotationFactorPerFrame = 15.0f;
float runMultiplier = 3.0f;
// Start is called before the first frame update
void Start()
{
_camera = Camera.main;
}
void Awake()
{
playerInput = new PlayerInput();
characterController = GetComponent<CharacterController>();
animator = GetComponent<Animator>();
isWalkingHash = Animator.StringToHash("isWalking");
isRunningHash = Animator.StringToHash("isRunning");
playerInput.CharacterControls.Move.started += onMovementInput;
playerInput.CharacterControls.Move.canceled += onMovementInput;
playerInput.CharacterControls.Move.performed += onMovementInput;
playerInput.CharacterControls.Run.started += onRun;
playerInput.CharacterControls.Run.canceled += onRun;
}
void onRun(InputAction.CallbackContext context)
{
isRunPressed = context.ReadValueAsButton();
}
void onMovementInput(InputAction.CallbackContext context)
{
currentMovementInput = context.ReadValue<Vector2>();
currentMovement.x = currentMovementInput.x;
currentMovement.z = currentMovementInput.y;
currentRunMovement.x = currentMovementInput.x * runMultiplier;
currentRunMovement.z = currentMovementInput.y * runMultiplier;
isMovementPressed = currentMovementInput.x != 0 || currentMovementInput.y != 0;
}
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);
}
else if ((isMovementPressed && !isRunPressed) && isRunning)
{
animator.SetBool(isRunningHash, false);
}
}
void handleGravity()
{
if (characterController.isGrounded)
{
float groundedGravity = -0.05f;
currentMovement.y = groundedGravity;
currentRunMovement.y = groundedGravity;
}
else
{
float gravity = -9.8f;
currentMovement.y = gravity;
currentRunMovement.y = gravity;
}
}
void handle_isRunPressed()
{
if (isRunPressed)
{
characterController.Move(currentRunMovement * Time.deltaTime);
}
else
{
characterController.Move(currentMovement * Time.deltaTime);
}
}
void handleRotation()
{
var mousePosition = playerInput.CharacterControls.MousePosition.ReadValue<Vector2>();
var mousePositionZ = _camera.farClipPlane * .5f;
var mouseWorldPosition = _camera.ScreenToWorldPoint(new Vector3(mousePosition.x, mousePosition.y, mousePositionZ)); // _camera.ScreenToViewportPoint(mousePosition);
// Get the angle between the points
// Use the x and z from the object/mouse, since we're looking along the y axis
var angle = AngleBetweenTwoPoints(new Vector2(transform.position.x, transform.position.z), new Vector2(mouseWorldPosition.x, mouseWorldPosition.z));
transform.rotation = Quaternion.Euler(new Vector3(0f, -angle, 0f));
}
float AngleBetweenTwoPoints(Vector3 a, Vector3 b)
{
return Mathf.Atan2(b.y - a.y, b.x - a.x) * Mathf.Rad2Deg;
}
// Update is called once per frame
void Update()
{
handleRotation();
handleAnimation();
handleGravity();
handle_isRunPressed();
}
void OnEnable()
{
playerInput.CharacterControls.Enable();
}
void OnDisable()
{
playerInput.CharacterControls.Disable();
}
}
Rotation still not working as intended with my code unforunately within handleRotation()
EDIT 3:
void handleRotation()
{
// We're getting a Vector2, whereas we will need a Vector3
// Get a z value based on camera, and include it in a Vector3
Vector2 mousePosition = playerInput.CharacterControls.MousePosition.ReadValue<Vector2>();
var mousePositionZ = _camera.farClipPlane * .5f;
Vector3 mouseViewportPosition = _camera.ViewportToWorldPoint(new Vector3(mousePosition.x, mousePosition.y, _camera.transform.position.y));
Debug.Log("MousePos: " + mouseViewportPosition);
Vector3 positionToLookAt;
positionToLookAt.x = mouseViewportPosition.x;
positionToLookAt.y = 0.0f;
//positionToLookAt.z = currentMovement.z;
positionToLookAt.z = mouseViewportPosition.z;
Quaternion currentRotation = transform.rotation;
Quaternion targetRotation = Quaternion.LookRotation(positionToLookAt - transform.position);
transform.rotation = Quaternion.Slerp(currentRotation, targetRotation, rotationFactorPerFrame * Time.deltaTime);
}
IT'S ROTATING. But not correctly.

