projectEli/Assets/Scripts/FirstPersonController.cs

300 lines
11 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using SimpleInventorySystem;
public class FirstPersonController : MonoBehaviour
{
public InventorySystem inventorySystem; // Reference to the InventorySystem script
// Flags for various character states and actions
public bool CanMove { get; private set; } = true;
private bool IsSprinting => canSprint && Input.GetKey(sprintKey);
private bool ShouldJump => Input.GetKeyDown(jumpKey) && characterController.isGrounded;
private bool ShouldCrouch => Input.GetKeyDown(crouchKey) && !duringCrouchAnimation && characterController.isGrounded;
[Header("Functional Options")]
[SerializeField] private bool canSprint = true;
[SerializeField] private bool canJump = true;
[SerializeField] private bool canCrouch = true;
[SerializeField] private bool canUseHeadbob = true;
[SerializeField] private bool canLean = true;
[Header("Controls")]
[SerializeField] private KeyCode sprintKey = KeyCode.LeftShift;
[SerializeField] private KeyCode jumpKey = KeyCode.Space;
[SerializeField] private KeyCode crouchKey = KeyCode.C;
[Header("Movement Parameters")]
[SerializeField] private float minWalkSpeed = 1.0f;
[SerializeField] private float maxWalkSpeed = 5.0f;
[SerializeField] private float walkSpeedInterval = 0.5f;
private float currentWalkSpeed;
[SerializeField] private float walkSpeed = 3.0f;
[SerializeField] private float sprintSpeed = 6.0f;
[SerializeField] private float crouchSpeed = 1.5f;
[Header("Look Parameters")]
[SerializeField, Range(1, 10)] private float lookSpeedX = 2.0f;
[SerializeField, Range(1, 10)] private float lookSpeedY = 2.0f;
[SerializeField, Range(1, 180)] private float upperLookLimit = 80.0f;
[SerializeField, Range(1, 180)] private float lowerLookLimit = 80.0f;
[Header("Leaning Parameters")]
[SerializeField] private bool toggleLeaning = false; // Toggle mode
[SerializeField] private KeyCode leanLeftKey = KeyCode.Q;
[SerializeField] private KeyCode leanRightKey = KeyCode.E;
[SerializeField, Range(1, 45)] private float maxLeaningAngle = 15.0f;
private float currentLeaningAngle;
private bool isLeaningLeft;
private bool isLeaningRight;
[Header("Jumping Parameters")]
[SerializeField] private float jumpForce = 8.0f;
[SerializeField] private float gravity = 30.0f;
[Header("Crouch Parameters")]
[SerializeField] private float crouchHeightInterval = 0.1f;
[SerializeField] private float crouchHeight = 0.5f;
[SerializeField] private float standingHeight = 2.0f;
[SerializeField] private float timeToCrouch = 0.25f;
[SerializeField] private Vector3 crouchingCenter = new Vector3(0, 0.5f, 0);
[SerializeField] private Vector3 standingCenter = new Vector3(0, 0, 0);
private bool isCrouching;
private bool duringCrouchAnimation;
private float targetCrouchHeight; // The target crouch height to apply when "C" key is released
private float tempCrouchHeight; // The temporary crouch height while "C" key is held
private float currentCrouchHeight;
private float minCrouchHeight = 0.5f; // Minimum crouch height
private bool isCrouchKeyHeld;
[Header("Headbob Parameters")]
[SerializeField] private float walkBobSpeed = 14f;
[SerializeField] private float walkBobAmount = 0.05f;
[SerializeField] private float sprintBobSpeed = 18f;
[SerializeField] private float sprintBobAmount = 0.1f;
[SerializeField] private float crouchBobSpeed = 8f;
[SerializeField] private float crouchBobAmount = 0.025f;
private float defaultYPos = 0;
private float timer;
private Camera playerCamera;
private CharacterController characterController;
private Vector3 moveDirection;
private Vector2 currentInput;
private float rotationX = 0;
void Awake()
{
playerCamera = GetComponentInChildren<Camera>();
characterController = GetComponent<CharacterController>();
defaultYPos = playerCamera.transform.localPosition.y;
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
currentWalkSpeed = walkSpeed;
currentCrouchHeight = crouchHeight;
}
void Update()
{
bool isInventoryUIOpen = inventorySystem.IsUsingInventoryMenuUI();
if (isInventoryUIOpen)
{
CanMove = false; // Disable movement when inventory UI is open
}
else
{
CanMove = true; // Enable movement
HandleMovementInput();
HandleMouseLook();
HandleSpeedChange();
HandleCrouchAdjustment();
if (canJump)
HandleJump();
if (canCrouch)
HandleCrouch();
if (canUseHeadbob)
HandleHeadbob();
if (canLean)
HandleLeaning(); // Process leaning logic
ApplyFinalMovements();
}
}
private void HandleMovementInput()
{
// Determine the current speed based on the character's state (crouching, sprinting, etc.)
currentInput = new Vector2((isCrouching ? crouchSpeed : IsSprinting ? sprintSpeed : walkSpeed) * Input.GetAxis("Vertical"), (isCrouching ? crouchSpeed : IsSprinting ? sprintSpeed : walkSpeed) * Input.GetAxis("Horizontal"));
float moveDirectionY = moveDirection.y;
moveDirection = (transform.TransformDirection(Vector3.forward) * currentInput.x) + (transform.TransformDirection(Vector3.right) * currentInput.y);
moveDirection.y = moveDirectionY;
}
private void HandleJump()
{
if (ShouldJump)
moveDirection.y = jumpForce; // Apply jump force
}
private void HandleCrouch()
{
if (Input.GetKeyDown(crouchKey) && !duringCrouchAnimation && characterController.isGrounded)
{
isCrouchKeyHeld = true;
tempCrouchHeight = currentCrouchHeight;
}
if (Input.GetKeyUp(crouchKey) && isCrouchKeyHeld)
{
// Apply the new crouch height when "C" key is released
targetCrouchHeight = tempCrouchHeight;
isCrouchKeyHeld = false;
StartCoroutine(CrouchStand());
}
}
private void HandleCrouchAdjustment()
{
// Adjust crouch height based on mouse scroll input
float scroll = Input.GetAxis("Mouse ScrollWheel");
if (scroll > 0 && tempCrouchHeight < standingHeight)
{
tempCrouchHeight += crouchHeightInterval;
}
else if (scroll < 0 && tempCrouchHeight > minCrouchHeight)
{
tempCrouchHeight -= crouchHeightInterval;
}
crouchHeight = tempCrouchHeight; // Update crouch height
}
private IEnumerator CrouchStand()
{
if (isCrouching && Physics.Raycast(playerCamera.transform.position, Vector3.up, 1f))
yield break;
duringCrouchAnimation = true;
float timeElapsed = 0;
float targetHeight = isCrouching ? standingHeight : currentCrouchHeight;
float currentHeight = characterController.height;
Vector3 targetCenter = isCrouching ? standingCenter : crouchingCenter;
Vector3 currentCenter = characterController.center;
// Smooth transition between crouch and stand
while (timeElapsed < timeToCrouch)
{
characterController.height = Mathf.Lerp(currentHeight, targetHeight, timeElapsed / timeToCrouch);
characterController.center = Vector3.Lerp(currentCenter, targetCenter, timeElapsed / timeToCrouch);
timeElapsed += Time.deltaTime;
yield return null;
}
characterController.height = targetHeight;
characterController.center = targetCenter;
isCrouching = !isCrouching;
duringCrouchAnimation = false;
crouchHeight = currentCrouchHeight; // Update to current crouch height
}
private void HandleHeadbob()
{
if (!characterController.isGrounded) return;
// Apply head bobbing effect based on movement speed and type
if (Mathf.Abs(moveDirection.x) > 0.1f || Mathf.Abs(moveDirection.z) > 0.1f)
{
timer += Time.deltaTime * (isCrouching ? crouchBobSpeed : IsSprinting ? sprintBobSpeed : walkBobSpeed);
playerCamera.transform.localPosition = new Vector3(
playerCamera.transform.localPosition.x,
defaultYPos + Mathf.Sin(timer) * (isCrouching ? crouchBobAmount : IsSprinting ? sprintBobAmount : walkBobAmount),
playerCamera.transform.localPosition.z);
}
}
private void HandleMouseLook()
{
rotationX -= Input.GetAxis("Mouse Y") * lookSpeedY;
rotationX = Mathf.Clamp(rotationX, -upperLookLimit, lowerLookLimit);
// Apply current leaning angle to camera's rotation
playerCamera.transform.localRotation = Quaternion.Euler(rotationX + currentLeaningAngle, 0, 0);
transform.rotation *= Quaternion.Euler(0, Input.GetAxis("Mouse X") * lookSpeedX, 0);
}
private void HandleLeaning()
{
if (toggleLeaning)
{
// Toggle leaning with a single key press
if (Input.GetKeyDown(leanLeftKey))
{
isLeaningLeft = !isLeaningLeft;
isLeaningRight = false;
}
if (Input.GetKeyDown(leanRightKey))
{
isLeaningRight = !isLeaningRight;
isLeaningLeft = false;
}
}
else
{
// Continuous leaning while the keys are held down
if (Input.GetKey(leanLeftKey) && !isLeaningRight)
{
isLeaningLeft = true;
isLeaningRight = false;
}
if (Input.GetKey(leanRightKey) && !isLeaningLeft)
{
isLeaningRight = true;
isLeaningLeft = false;
}
}
// Calculate and apply the current leaning angle
currentLeaningAngle = isLeaningLeft ? -maxLeaningAngle : isLeaningRight ? maxLeaningAngle : 0;
}
private void ApplyFinalMovements()
{
if (!characterController.isGrounded)
moveDirection.y -= gravity * Time.deltaTime;
characterController.Move(moveDirection * Time.deltaTime);
}
private void HandleSpeedChange()
{
float scroll = Input.GetAxis("Mouse ScrollWheel");
// Adjust walking speed based on mouse scroll input
if (scroll > 0 && currentWalkSpeed < maxWalkSpeed)
{
currentWalkSpeed += walkSpeedInterval;
}
else if (scroll < 0 && currentWalkSpeed > minWalkSpeed)
{
currentWalkSpeed -= walkSpeedInterval;
}
walkSpeed = currentWalkSpeed; // Update walk speed
}
}