playtest-unity/playtest/Assets/Scripts/Player/Movement/PlayerController.cs

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
}
}
}
}
}