275 lines
8.0 KiB
C#
275 lines
8.0 KiB
C#
using UnityEngine;
|
|
|
|
namespace Movement
|
|
{
|
|
[RequireComponent(typeof(CharacterController))]
|
|
public class PlayerController : MonoBehaviour
|
|
{
|
|
[System.Serializable]
|
|
public class MovementSettings
|
|
{
|
|
public float MaxSpeed;
|
|
public float Acceleration;
|
|
public float Deceleration;
|
|
|
|
public MovementSettings(float maxSpeed, float accel, float decel)
|
|
{
|
|
MaxSpeed = maxSpeed;
|
|
Acceleration = accel;
|
|
Deceleration = decel;
|
|
}
|
|
}
|
|
|
|
[Header("Aiming")]
|
|
[SerializeField] private Camera m_Camera;
|
|
[SerializeField] private MouseLook m_MouseLook = new MouseLook();
|
|
|
|
[Header("Movement")]
|
|
[SerializeField] private float m_Friction = 6;
|
|
[SerializeField] private float m_Gravity = 20;
|
|
[SerializeField] private float m_JumpForce = 8;
|
|
[Tooltip("How precise air control is")]
|
|
[SerializeField] private float m_AirControl = 0.3f;
|
|
[SerializeField] private MovementSettings m_GroundSettings = new MovementSettings(7, 14, 10);
|
|
[SerializeField] private MovementSettings m_AirSettings = new MovementSettings(7, 2, 2);
|
|
[SerializeField] private MovementSettings m_StrafeSettings = new MovementSettings(1, 50, 50);
|
|
[SerializeField] private float m_SprintMultiplier = 1.5f;
|
|
[SerializeField] private float m_BhopMultiplier = 1.2f;
|
|
|
|
public float Speed { get { return m_Character.velocity.magnitude; } }
|
|
|
|
private CharacterController m_Character;
|
|
private Vector3 m_MoveDirectionNorm = Vector3.zero;
|
|
private Vector3 m_PlayerVelocity = Vector3.zero;
|
|
private bool m_IsCrouching = false;
|
|
|
|
private bool m_JumpQueued = false;
|
|
|
|
private Vector3 m_MoveInput;
|
|
private Transform m_Tran;
|
|
private Transform m_CamTran;
|
|
|
|
private void Start()
|
|
{
|
|
m_Tran = transform;
|
|
m_Character = GetComponent<CharacterController>();
|
|
|
|
if (!m_Camera)
|
|
m_Camera = Camera.main;
|
|
|
|
m_CamTran = m_Camera.transform;
|
|
m_MouseLook.Init(m_Tran, m_CamTran);
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
m_MoveInput = new Vector3(Input.GetAxisRaw("Horizontal"), 0, Input.GetAxisRaw("Vertical"));
|
|
m_MouseLook.UpdateCursorLock();
|
|
QueueJump();
|
|
Crouch();
|
|
|
|
if (m_Character.isGrounded)
|
|
{
|
|
GroundMove();
|
|
}
|
|
else
|
|
{
|
|
AirMove();
|
|
}
|
|
|
|
m_MouseLook.LookRotation(m_Tran, m_CamTran);
|
|
m_Character.Move(m_PlayerVelocity * Time.deltaTime);
|
|
}
|
|
|
|
private void QueueJump()
|
|
{
|
|
m_JumpQueued = Input.GetButton("Jump");
|
|
}
|
|
|
|
private void AirMove()
|
|
{
|
|
float accel;
|
|
|
|
var wishdir = new Vector3(m_MoveInput.x, 0, m_MoveInput.z);
|
|
wishdir = m_Tran.TransformDirection(wishdir);
|
|
|
|
float wishspeed = wishdir.magnitude;
|
|
wishspeed *= m_AirSettings.MaxSpeed;
|
|
|
|
wishdir.Normalize();
|
|
m_MoveDirectionNorm = wishdir;
|
|
|
|
float wishspeed2 = wishspeed;
|
|
if (Vector3.Dot(m_PlayerVelocity, wishdir) < 0)
|
|
{
|
|
accel = m_AirSettings.Deceleration;
|
|
}
|
|
else
|
|
{
|
|
accel = m_AirSettings.Acceleration;
|
|
}
|
|
|
|
if (m_MoveInput.z == 0 && m_MoveInput.x != 0)
|
|
{
|
|
if (wishspeed > m_StrafeSettings.MaxSpeed)
|
|
{
|
|
wishspeed = m_StrafeSettings.MaxSpeed;
|
|
}
|
|
|
|
accel = m_StrafeSettings.Acceleration;
|
|
}
|
|
|
|
Accelerate(wishdir, wishspeed, accel);
|
|
if (m_AirControl > 0)
|
|
{
|
|
AirControl(wishdir, wishspeed2);
|
|
}
|
|
|
|
m_PlayerVelocity.y -= m_Gravity * Time.deltaTime;
|
|
}
|
|
|
|
private void AirControl(Vector3 targetDir, float targetSpeed)
|
|
{
|
|
if (Mathf.Abs(m_MoveInput.z) < 0.001 || Mathf.Abs(targetSpeed) < 0.001)
|
|
{
|
|
return;
|
|
}
|
|
|
|
float zSpeed = m_PlayerVelocity.y;
|
|
m_PlayerVelocity.y = 0;
|
|
float speed = m_PlayerVelocity.magnitude;
|
|
m_PlayerVelocity.Normalize();
|
|
|
|
float dot = Vector3.Dot(m_PlayerVelocity, targetDir);
|
|
float k = 32;
|
|
k *= m_AirControl * dot * dot * Time.deltaTime;
|
|
|
|
if (dot > 0)
|
|
{
|
|
m_PlayerVelocity.x *= speed + targetDir.x * k;
|
|
m_PlayerVelocity.y *= speed + targetDir.y * k;
|
|
m_PlayerVelocity.z *= speed + targetDir.z * k;
|
|
|
|
m_PlayerVelocity.Normalize();
|
|
m_MoveDirectionNorm = m_PlayerVelocity;
|
|
}
|
|
|
|
m_PlayerVelocity.x *= speed;
|
|
m_PlayerVelocity.y = zSpeed;
|
|
m_PlayerVelocity.z *= speed;
|
|
}
|
|
|
|
private void GroundMove()
|
|
{
|
|
if (!m_JumpQueued)
|
|
{
|
|
ApplyFriction(1.0f);
|
|
}
|
|
else
|
|
{
|
|
ApplyFriction(0);
|
|
}
|
|
|
|
var wishdir = new Vector3(m_MoveInput.x, 0, m_MoveInput.z);
|
|
wishdir = m_Tran.TransformDirection(wishdir);
|
|
wishdir.Normalize();
|
|
m_MoveDirectionNorm = wishdir;
|
|
|
|
var wishspeed = wishdir.magnitude;
|
|
wishspeed *= m_GroundSettings.MaxSpeed;
|
|
|
|
if (m_JumpQueued)
|
|
{
|
|
wishspeed *= m_BhopMultiplier;
|
|
}
|
|
|
|
if (Input.GetKey(KeyCode.LeftShift))
|
|
{
|
|
wishspeed *= m_SprintMultiplier;
|
|
}
|
|
|
|
if (m_IsCrouching)
|
|
{
|
|
wishspeed *= 0.5f;
|
|
}
|
|
|
|
Accelerate(wishdir, wishspeed, m_GroundSettings.Acceleration);
|
|
|
|
m_PlayerVelocity.y = -m_Gravity * Time.deltaTime;
|
|
|
|
if (m_JumpQueued)
|
|
{
|
|
m_PlayerVelocity.y = m_JumpForce;
|
|
m_JumpQueued = false;
|
|
}
|
|
}
|
|
|
|
private void ApplyFriction(float t)
|
|
{
|
|
Vector3 vec = m_PlayerVelocity;
|
|
vec.y = 0;
|
|
float speed = vec.magnitude;
|
|
float drop = 0;
|
|
|
|
if (m_Character.isGrounded)
|
|
{
|
|
float control = speed < m_GroundSettings.Deceleration ? m_GroundSettings.Deceleration : speed;
|
|
drop = control * m_Friction * Time.deltaTime * t;
|
|
}
|
|
|
|
float newSpeed = speed - drop;
|
|
if (newSpeed < 0)
|
|
{
|
|
newSpeed = 0;
|
|
}
|
|
|
|
if (speed > 0)
|
|
{
|
|
newSpeed /= speed;
|
|
}
|
|
|
|
m_PlayerVelocity.x *= newSpeed;
|
|
m_PlayerVelocity.z *= newSpeed;
|
|
}
|
|
|
|
private void Accelerate(Vector3 targetDir, float targetSpeed, float accel)
|
|
{
|
|
float currentspeed = Vector3.Dot(m_PlayerVelocity, targetDir);
|
|
float addspeed = targetSpeed - currentspeed;
|
|
if (addspeed <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
float accelspeed = accel * Time.deltaTime * targetSpeed;
|
|
if (accelspeed > addspeed)
|
|
{
|
|
accelspeed = addspeed;
|
|
}
|
|
|
|
m_PlayerVelocity.x += accelspeed * targetDir.x;
|
|
m_PlayerVelocity.z += accelspeed * targetDir.z;
|
|
}
|
|
|
|
private void Crouch()
|
|
{
|
|
if (Input.GetButton("Crouch"))
|
|
{
|
|
if (!m_IsCrouching)
|
|
{
|
|
m_IsCrouching = true;
|
|
m_Character.height = 0.5f; // Adjust the crouch height as needed
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (m_IsCrouching && m_Character.isGrounded)
|
|
{
|
|
m_IsCrouching = false;
|
|
m_Character.height = 2f; // Adjust the normal height as needed
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|