Hi everyone,
first of all I want to say thank you for the awesome 3rd Person Combat & Traversal course! I really enjoyed it so far. <3
My problem is, that I really don’t like the the behaviour of cinemachines free look camera. Everything feels so fast and weird. So I checked how the 3rd person starter assets work and I found that they use a normal virtual camera and set the Body to 3rd Person Follow
and the Aim to Do nothing
. I did some research and I found this official Unity video over on Youtube:
(79) Creating a Third Person Camera using Cinemachine in Unity! (Tutorial) - YouTube
I used there code to rotate the camera and ended up with this:
using UnityEngine;
public class PlayerFreeLookState : PlayerBaseState
{
public PlayerFreeLookState(PlayerStateMachine stateMachine) : base(stateMachine)
{
}
#region State Machine
public override void Enter()
{
stateMachine.InputReader.TargetEvent += OnTarget;
stateMachine.Animator.CrossFadeInFixedTime(
Constants.FreeLookBlendTreeHash,
Constants.CrossFadeDuration
);
}
public override void Tick(float deltaTime)
{
HandleStateChanges();
Vector3 movement = CalculateMovement();
Vector3 angles = HandleCameraRotation();
HandlePlayerMovement(movement, deltaTime);
HandlePlayerRotation(angles, deltaTime);
UpdateAnimator(deltaTime);
}
public override void Exit()
{
stateMachine.InputReader.TargetEvent -= OnTarget;
}
#endregion
#region Event Handlers
private void OnTarget()
{
if (!stateMachine.Targeter.SelectTarget()) return;
stateMachine.SwitchState(new PlayerTargetingState(stateMachine));
}
#endregion
private void HandleStateChanges()
{
if (stateMachine.InputReader.IsAttackingPrimary)
{
stateMachine.SwitchState(new PlayerAttackingState(stateMachine, 0));
}
}
private Vector3 CalculateMovement()
{
Vector3 forward = stateMachine.MainCameraTransform.forward;
forward.y = 0f;
forward.Normalize();
Vector3 right = stateMachine.MainCameraTransform.right;
right.y = 0f;
right.Normalize();
return forward * stateMachine.InputReader.MoveInput.y + right * stateMachine.InputReader.MoveInput.x;
}
private Vector3 HandleCameraRotation()
{
// Horizontal Rotation
stateMachine.CinemachineCameraTarget.transform.rotation *= Quaternion.AngleAxis(
stateMachine.InputReader.LookInput.x * stateMachine.RotationSpeed,
Vector3.up
);
// Vertical Rotation
stateMachine.CinemachineCameraTarget.transform.rotation *= Quaternion.AngleAxis(
stateMachine.InputReader.LookInput.y * stateMachine.RotationSpeed,
Vector3.right
);
Vector3 angles = stateMachine.CinemachineCameraTarget.transform.localEulerAngles;
angles.z = 0f;
float angle = angles.x;
// TODO: simplify this angle clamping
if (angle > 180f && angle < 340f)
{
angles.x = 340f;
}
else if (angle < 180f && angle > 40f)
{
angles.x = 40f;
}
stateMachine.CinemachineCameraTarget.transform.localEulerAngles = angles;
return angles;
}
private void HandlePlayerMovement(Vector3 movement, float deltaTime)
{
Move(movement * stateMachine.FreeLookSpeed, deltaTime);
}
private void HandlePlayerRotation(Vector3 angles, float deltaTime)
{
if (!stateMachine.InputReader.IsMoving) return;
stateMachine.transform.rotation = Quaternion.Euler(
0f,
stateMachine.CinemachineCameraTarget.transform.rotation.eulerAngles.y,
0f
);
stateMachine.CinemachineCameraTarget.transform.localEulerAngles = new Vector3(
angles.x,
0f,
0f
);
}
private void UpdateAnimator(float deltaTime)
{
stateMachine.Animator.SetFloat(
Constants.FreeLookSpeedHash,
stateMachine.InputReader.IsMoving
? stateMachine.InputReader.IsWalking
? Constants.WalkSpeed
: Constants.RunSpeed
: 0f,
Constants.AnimationDampTime,
deltaTime
);
}
// private void RotatePlayerToMovementDirection(Vector3 movement, float deltaTime)
// {
// if (!stateMachine.InputReader.IsMoving) return;
// stateMachine.transform.rotation = Quaternion.Lerp(
// stateMachine.transform.rotation,
// Quaternion.LookRotation(movement),
// deltaTime * Constants.RotationDamping
// );
// }
}
I think this feels and works great. Now I just have two problems.
The first problem is, that my character doesn’t turn into it’s move direction and I don’t understand why. Here is a short video:
Character Doesn’t Turn In Free Look State
Anyone has some advices to let my character turn into the movement direction based on the code above?
The 2nd problem I have is, that I would like to simplify the angle clamping. Something like Mathf.Clamp()
. But I don’t really get the bottom and top values out of this if construction. Maybe you got some hints how to simplify that?
I really appreciate any tips and advices and I really thank you in advance for your help.