StellarXipher/Assets/StarterAssets/FirstPersonController/Scripts/FirstPersonController.cs
nlevin6 1c0bc1cf7c
All checks were successful
Build project / Build for (StandaloneLinux64, 6000.0.37f1) (push) Successful in 5m20s
Build project / Build for (StandaloneWindows64, 6000.0.37f1) (push) Successful in 5m3s
Build project / Publish to itch.io (StandaloneLinux64) (push) Successful in 4s
Build project / Publish to itch.io (StandaloneWindows64) (push) Successful in 5s
Added ladder climbing and pause menu
2025-03-15 21:07:20 -04:00

226 lines
7.7 KiB
C#

using UnityEngine;
#if ENABLE_INPUT_SYSTEM
using UnityEngine.InputSystem;
#endif
namespace StarterAssets
{
[RequireComponent(typeof(CharacterController))]
#if ENABLE_INPUT_SYSTEM
[RequireComponent(typeof(PlayerInput))]
#endif
public class FirstPersonController : MonoBehaviour
{
public float MoveSpeed = 4.0f;
public float SprintSpeed = 6.0f;
public float RotationSpeed = 1.0f;
public float SpeedChangeRate = 10.0f;
public float JumpHeight = 1.2f;
public float Gravity = -15.0f;
public float JumpTimeout = 0.1f;
public float FallTimeout = 0.15f;
public bool Grounded = true;
public float GroundedOffset = -0.14f;
public float GroundedRadius = 0.5f;
public LayerMask GroundLayers;
public GameObject CinemachineCameraTarget;
public float TopClamp = 90.0f;
public float BottomClamp = -90.0f;
private float _cinemachineTargetPitch;
private float _speed;
private float _rotationVelocity;
private float _verticalVelocity;
private float _terminalVelocity = 53.0f;
private float _jumpTimeoutDelta;
private float _fallTimeoutDelta;
#if ENABLE_INPUT_SYSTEM
private PlayerInput _playerInput;
#endif
private CharacterController _controller;
private StarterAssetsInputs _input;
private GameObject _mainCamera;
private const float _threshold = 0.01f;
private bool isClimbing = false;
public float LadderClimbSpeed = 3.0f;
private bool IsCurrentDeviceMouse
{
get
{
#if ENABLE_INPUT_SYSTEM
return _playerInput.currentControlScheme == "KeyboardMouse";
#else
return false;
#endif
}
}
private void Awake()
{
if (_mainCamera == null)
{
_mainCamera = GameObject.FindGameObjectWithTag("MainCamera");
}
}
private void Start()
{
_controller = GetComponent<CharacterController>();
_input = GetComponent<StarterAssetsInputs>();
#if ENABLE_INPUT_SYSTEM
_playerInput = GetComponent<PlayerInput>();
#else
Debug.LogError("Starter Assets package is missing dependencies. Please use Tools/Starter Assets/Reinstall Dependencies to fix it");
#endif
_jumpTimeoutDelta = JumpTimeout;
_fallTimeoutDelta = FallTimeout;
}
private void Update()
{
if (isClimbing)
{
LadderClimb();
}
else
{
JumpAndGravity();
GroundedCheck();
Move();
}
}
private void LateUpdate()
{
CameraRotation();
}
private void GroundedCheck()
{
Vector3 spherePosition = new Vector3(transform.position.x, transform.position.y - GroundedOffset, transform.position.z);
Grounded = Physics.CheckSphere(spherePosition, GroundedRadius, GroundLayers, QueryTriggerInteraction.Ignore);
}
private void CameraRotation()
{
if (_input.look.sqrMagnitude >= _threshold)
{
float deltaTimeMultiplier = IsCurrentDeviceMouse ? 1.0f : Time.deltaTime;
_cinemachineTargetPitch += _input.look.y * RotationSpeed * deltaTimeMultiplier;
_rotationVelocity = _input.look.x * RotationSpeed * deltaTimeMultiplier;
_cinemachineTargetPitch = ClampAngle(_cinemachineTargetPitch, BottomClamp, TopClamp);
CinemachineCameraTarget.transform.localRotation = Quaternion.Euler(_cinemachineTargetPitch, 0.0f, 0.0f);
transform.Rotate(Vector3.up * _rotationVelocity);
}
}
private void Move()
{
float targetSpeed = _input.sprint ? SprintSpeed : MoveSpeed;
if (_input.move == Vector2.zero)
targetSpeed = 0.0f;
float currentHorizontalSpeed = new Vector3(_controller.velocity.x, 0.0f, _controller.velocity.z).magnitude;
float speedOffset = 0.1f;
float inputMagnitude = _input.analogMovement ? _input.move.magnitude : 1f;
if (currentHorizontalSpeed < targetSpeed - speedOffset || currentHorizontalSpeed > targetSpeed + speedOffset)
{
_speed = Mathf.Lerp(currentHorizontalSpeed, targetSpeed * inputMagnitude, Time.deltaTime * SpeedChangeRate);
_speed = Mathf.Round(_speed * 1000f) / 1000f;
}
else
{
_speed = targetSpeed;
}
Vector3 inputDirection = new Vector3(_input.move.x, 0.0f, _input.move.y).normalized;
if (_input.move != Vector2.zero)
{
inputDirection = transform.right * _input.move.x + transform.forward * _input.move.y;
}
_controller.Move(inputDirection.normalized * (_speed * Time.deltaTime) + new Vector3(0.0f, _verticalVelocity, 0.0f) * Time.deltaTime);
}
private void JumpAndGravity()
{
if (Grounded)
{
_fallTimeoutDelta = FallTimeout;
if (_verticalVelocity < 0.0f)
{
_verticalVelocity = -2f;
}
if (_input.jump && _jumpTimeoutDelta <= 0.0f)
{
_verticalVelocity = Mathf.Sqrt(JumpHeight * -2f * Gravity);
}
if (_jumpTimeoutDelta >= 0.0f)
{
_jumpTimeoutDelta -= Time.deltaTime;
}
}
else
{
_jumpTimeoutDelta = JumpTimeout;
if (_fallTimeoutDelta >= 0.0f)
{
_fallTimeoutDelta -= Time.deltaTime;
}
_input.jump = false;
}
if (_verticalVelocity < _terminalVelocity)
{
_verticalVelocity += Gravity * Time.deltaTime;
}
}
private static float ClampAngle(float lfAngle, float lfMin, float lfMax)
{
if (lfAngle < -360f)
lfAngle += 360f;
if (lfAngle > 360f)
lfAngle -= 360f;
return Mathf.Clamp(lfAngle, lfMin, lfMax);
}
private void LadderClimb()
{
if (_input.jump || Mathf.Abs(_input.move.x) > 0.1f)
{
isClimbing = false;
_controller.slopeLimit = 45f;
_controller.Move(transform.forward * MoveSpeed * Time.deltaTime);
return;
}
float climbVelocity = _input.move.y * LadderClimbSpeed;
Vector3 moveVector = new Vector3(0, climbVelocity, 0);
_controller.Move(moveVector * Time.deltaTime);
}
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Ladder"))
{
isClimbing = true;
_controller.slopeLimit = 90f;
}
}
private void OnTriggerExit(Collider other)
{
if (other.CompareTag("Ladder"))
{
isClimbing = false;
_controller.slopeLimit = 45f;
}
}
private void OnDrawGizmosSelected()
{
Color transparentGreen = new Color(0.0f, 1.0f, 0.0f, 0.35f);
Color transparentRed = new Color(1.0f, 0.0f, 0.0f, 0.35f);
Gizmos.color = Grounded ? transparentGreen : transparentRed;
Gizmos.DrawSphere(new Vector3(transform.position.x, transform.position.y - GroundedOffset, transform.position.z), GroundedRadius);
}
}
}