2022-10-08 02:26:09 +00:00
|
|
|
|
using System.Collections;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
2023-10-31 20:13:36 +00:00
|
|
|
|
using SimpleInventorySystem;
|
|
|
|
|
|
2022-10-08 02:26:09 +00:00
|
|
|
|
public class FirstPersonController : MonoBehaviour
|
|
|
|
|
{
|
2023-10-31 20:13:36 +00:00
|
|
|
|
public InventorySystem inventorySystem; // Reference to the InventorySystem script
|
|
|
|
|
|
2022-10-08 02:26:09 +00:00
|
|
|
|
// Start is called before the first frame update
|
|
|
|
|
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;
|
2023-10-31 20:13:36 +00:00
|
|
|
|
[SerializeField] private bool canUseHeadbob = true;
|
2023-11-03 16:51:11 +00:00
|
|
|
|
[SerializeField] private bool canLean = true;
|
|
|
|
|
|
2022-10-08 02:26:09 +00:00
|
|
|
|
|
|
|
|
|
[Header("Controls")]
|
|
|
|
|
[SerializeField] private KeyCode sprintKey = KeyCode.LeftShift;
|
|
|
|
|
[SerializeField] private KeyCode jumpKey = KeyCode.Space;
|
|
|
|
|
[SerializeField] private KeyCode crouchKey = KeyCode.C;
|
|
|
|
|
|
|
|
|
|
[Header("Movement Parameters")]
|
2023-10-31 20:25:12 +00:00
|
|
|
|
[SerializeField] private float minWalkSpeed = 1.0f;
|
|
|
|
|
[SerializeField] private float maxWalkSpeed = 5.0f;
|
|
|
|
|
[SerializeField] private float walkSpeedInterval = 0.5f;
|
|
|
|
|
private float currentWalkSpeed;
|
|
|
|
|
|
2023-11-03 16:04:59 +00:00
|
|
|
|
|
2022-10-08 02:26:09 +00:00
|
|
|
|
[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;
|
|
|
|
|
|
2023-11-03 16:51:11 +00:00
|
|
|
|
|
|
|
|
|
[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;
|
|
|
|
|
|
|
|
|
|
|
2022-10-08 02:26:09 +00:00
|
|
|
|
[Header("Jumping Parameters")]
|
|
|
|
|
[SerializeField] private float jumpForce = 8.0f;
|
|
|
|
|
[SerializeField] private float gravity = 30.0f;
|
|
|
|
|
|
|
|
|
|
[Header("Crouch Parameters")]
|
2023-11-03 16:04:59 +00:00
|
|
|
|
[SerializeField] private float crouchHeightInterval = 0.1f;
|
2022-10-08 02:26:09 +00:00
|
|
|
|
[SerializeField] private float crouchHeight = 0.5f;
|
|
|
|
|
[SerializeField] private float standingHeight = 2.0f;
|
|
|
|
|
[SerializeField] private float timeToCrouch = 0.25f;
|
2023-10-31 20:13:36 +00:00
|
|
|
|
[SerializeField] private Vector3 crouchingCenter = new Vector3(0, 0.5f, 0);
|
|
|
|
|
[SerializeField] private Vector3 standingCenter = new Vector3(0, 0, 0);
|
2022-10-08 02:26:09 +00:00
|
|
|
|
private bool isCrouching;
|
|
|
|
|
private bool duringCrouchAnimation;
|
|
|
|
|
|
2023-11-03 16:04:59 +00:00
|
|
|
|
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;
|
|
|
|
|
private bool crouchHeightAdjustmentEnabled; // Flag to enable crouch height adjustment
|
|
|
|
|
|
2022-10-08 02:26:09 +00:00
|
|
|
|
[Header("Headbob Parameters")]
|
|
|
|
|
[SerializeField] private float walkBobSpeed = 14f;
|
|
|
|
|
[SerializeField] private float walkBobAmount = 0.05f;
|
|
|
|
|
[SerializeField] private float sprintBobSpeed = 18f;
|
2023-10-31 20:13:36 +00:00
|
|
|
|
[SerializeField] private float sprintBobAmount = 0.1f;
|
2022-10-08 02:26:09 +00:00
|
|
|
|
[SerializeField] private float crouchBobSpeed = 8f;
|
|
|
|
|
[SerializeField] private float crouchBobAmount = 0.025f;
|
|
|
|
|
private float defaultYPos = 0;
|
2023-10-31 20:13:36 +00:00
|
|
|
|
private float timer;
|
2022-10-08 02:26:09 +00:00
|
|
|
|
|
|
|
|
|
private Camera playerCamera;
|
|
|
|
|
private CharacterController characterController;
|
|
|
|
|
|
|
|
|
|
private Vector3 moveDirection;
|
|
|
|
|
private Vector2 currentInput;
|
|
|
|
|
|
|
|
|
|
private float rotationX = 0;
|
2023-10-31 20:13:36 +00:00
|
|
|
|
|
2022-10-08 02:26:09 +00:00
|
|
|
|
void Awake()
|
|
|
|
|
{
|
|
|
|
|
playerCamera = GetComponentInChildren<Camera>();
|
|
|
|
|
characterController = GetComponent<CharacterController>();
|
|
|
|
|
defaultYPos = playerCamera.transform.localPosition.y;
|
|
|
|
|
Cursor.lockState = CursorLockMode.Locked;
|
|
|
|
|
Cursor.visible = false;
|
2023-10-31 20:25:12 +00:00
|
|
|
|
currentWalkSpeed = walkSpeed;
|
2023-11-03 16:04:59 +00:00
|
|
|
|
currentCrouchHeight = crouchHeight;
|
2022-10-08 02:26:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update is called once per frame
|
|
|
|
|
void Update()
|
|
|
|
|
{
|
2023-10-31 20:13:36 +00:00
|
|
|
|
// Check if the inventory UI is open
|
|
|
|
|
bool isInventoryUIOpen = inventorySystem.IsUsingInventoryMenuUI();
|
|
|
|
|
|
|
|
|
|
if (isInventoryUIOpen)
|
|
|
|
|
{
|
|
|
|
|
// The inventory UI is open, disable movement
|
|
|
|
|
CanMove = false;
|
|
|
|
|
}
|
|
|
|
|
else
|
2022-10-08 02:26:09 +00:00
|
|
|
|
{
|
2023-10-31 20:13:36 +00:00
|
|
|
|
// The inventory UI is closed, enable movement
|
|
|
|
|
CanMove = true;
|
2022-10-08 02:26:09 +00:00
|
|
|
|
HandleMovementInput();
|
|
|
|
|
HandleMouseLook();
|
2023-10-31 20:25:12 +00:00
|
|
|
|
HandleSpeedChange();
|
2023-11-03 16:04:59 +00:00
|
|
|
|
HandleCrouchAdjustment();
|
2022-10-08 02:26:09 +00:00
|
|
|
|
|
|
|
|
|
if (canJump)
|
|
|
|
|
HandleJump();
|
|
|
|
|
|
|
|
|
|
if (canCrouch)
|
|
|
|
|
HandleCrouch();
|
|
|
|
|
|
|
|
|
|
if (canUseHeadbob)
|
|
|
|
|
HandleHeadbob();
|
|
|
|
|
|
2023-11-03 16:51:11 +00:00
|
|
|
|
if (canLean)
|
|
|
|
|
HandleLeaning(); // Added the HandleLeaning method call here.
|
|
|
|
|
|
2022-10-08 02:26:09 +00:00
|
|
|
|
ApplyFinalMovements();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-31 20:13:36 +00:00
|
|
|
|
|
|
|
|
|
|
2022-10-08 02:26:09 +00:00
|
|
|
|
private void HandleMovementInput()
|
|
|
|
|
{
|
2023-10-31 20:13:36 +00:00
|
|
|
|
currentInput = new Vector2((isCrouching ? crouchSpeed : IsSprinting ? sprintSpeed : walkSpeed) * Input.GetAxis("Vertical"), (isCrouching ? crouchSpeed : IsSprinting ? sprintSpeed : walkSpeed) * Input.GetAxis("Horizontal"));
|
2022-10-08 02:26:09 +00:00
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void HandleCrouch()
|
|
|
|
|
{
|
2023-11-03 16:04:59 +00:00
|
|
|
|
if (Input.GetKeyDown(crouchKey) && !duringCrouchAnimation && characterController.isGrounded)
|
2022-10-08 02:26:09 +00:00
|
|
|
|
{
|
2023-11-03 16:04:59 +00:00
|
|
|
|
isCrouchKeyHeld = true;
|
|
|
|
|
tempCrouchHeight = currentCrouchHeight;
|
|
|
|
|
crouchHeightAdjustmentEnabled = true; // Enable crouch height adjustment
|
2022-10-08 02:26:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-11-03 16:04:59 +00:00
|
|
|
|
if (Input.GetKeyUp(crouchKey) && isCrouchKeyHeld)
|
|
|
|
|
{
|
|
|
|
|
// "C" key is released, apply the new crouch height
|
|
|
|
|
targetCrouchHeight = tempCrouchHeight;
|
|
|
|
|
isCrouchKeyHeld = false;
|
|
|
|
|
StartCoroutine(CrouchStand());
|
|
|
|
|
}
|
2022-10-08 02:26:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-11-03 16:04:59 +00:00
|
|
|
|
private void HandleCrouchAdjustment()
|
2022-10-08 02:26:09 +00:00
|
|
|
|
{
|
2023-11-03 16:04:59 +00:00
|
|
|
|
// Adjust the crouch height based on the scroll wheel input
|
|
|
|
|
float scroll = Input.GetAxis("Mouse ScrollWheel");
|
2022-10-08 02:26:09 +00:00
|
|
|
|
|
2023-11-03 16:04:59 +00:00
|
|
|
|
if (scroll > 0)
|
|
|
|
|
{
|
|
|
|
|
// Increase temporary crouch height if within the maximum limit
|
|
|
|
|
if (tempCrouchHeight < standingHeight)
|
|
|
|
|
{
|
|
|
|
|
tempCrouchHeight += crouchHeightInterval;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (scroll < 0)
|
|
|
|
|
{
|
|
|
|
|
// Decrease temporary crouch height if within the minimum limit
|
|
|
|
|
if (tempCrouchHeight > minCrouchHeight)
|
|
|
|
|
{
|
|
|
|
|
tempCrouchHeight -= crouchHeightInterval;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-10-08 02:26:09 +00:00
|
|
|
|
|
2023-11-03 16:04:59 +00:00
|
|
|
|
// Update the actual crouch height with the temporary crouch height
|
|
|
|
|
crouchHeight = tempCrouchHeight;
|
2023-10-31 20:13:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-10-08 02:26:09 +00:00
|
|
|
|
private IEnumerator CrouchStand()
|
|
|
|
|
{
|
|
|
|
|
if (isCrouching && Physics.Raycast(playerCamera.transform.position, Vector3.up, 1f))
|
2023-10-31 20:13:36 +00:00
|
|
|
|
yield break;
|
2022-10-08 02:26:09 +00:00
|
|
|
|
duringCrouchAnimation = true;
|
|
|
|
|
|
|
|
|
|
float timeElapsed = 0;
|
2023-11-03 16:04:59 +00:00
|
|
|
|
float targetHeight = isCrouching ? standingHeight : currentCrouchHeight; // Use currentCrouchHeight here
|
2022-10-08 02:26:09 +00:00
|
|
|
|
float currentHeight = characterController.height;
|
|
|
|
|
Vector3 targetCenter = isCrouching ? standingCenter : crouchingCenter;
|
|
|
|
|
Vector3 currentCenter = characterController.center;
|
|
|
|
|
|
|
|
|
|
while (timeElapsed < timeToCrouch)
|
|
|
|
|
{
|
|
|
|
|
characterController.height = Mathf.Lerp(currentHeight, targetHeight, timeElapsed / timeToCrouch);
|
2023-11-03 16:04:59 +00:00
|
|
|
|
characterController.center = Vector3.Lerp(currentCenter, targetCenter, timeElapsed / timeToCrouch);
|
2022-10-08 02:26:09 +00:00
|
|
|
|
timeElapsed += Time.deltaTime;
|
|
|
|
|
yield return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
characterController.height = targetHeight;
|
|
|
|
|
characterController.center = targetCenter;
|
|
|
|
|
|
|
|
|
|
isCrouching = !isCrouching;
|
|
|
|
|
duringCrouchAnimation = false;
|
2023-11-03 16:04:59 +00:00
|
|
|
|
|
|
|
|
|
// Update crouchHeight with currentCrouchHeight
|
|
|
|
|
crouchHeight = currentCrouchHeight;
|
2022-10-08 02:26:09 +00:00
|
|
|
|
}
|
2023-11-03 16:04:59 +00:00
|
|
|
|
|
|
|
|
|
private void HandleHeadbob()
|
|
|
|
|
{
|
|
|
|
|
if (!characterController.isGrounded) return;
|
|
|
|
|
|
|
|
|
|
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);
|
2023-11-03 16:51:11 +00:00
|
|
|
|
|
|
|
|
|
// Apply the current leaning angle to the camera's rotation
|
|
|
|
|
playerCamera.transform.localRotation = Quaternion.Euler(rotationX + currentLeaningAngle, 0, 0);
|
2023-11-03 16:04:59 +00:00
|
|
|
|
transform.rotation *= Quaternion.Euler(0, Input.GetAxis("Mouse X") * lookSpeedX, 0);
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-03 16:51:11 +00:00
|
|
|
|
private void HandleLeaning()
|
|
|
|
|
{
|
|
|
|
|
if (toggleLeaning)
|
|
|
|
|
{
|
|
|
|
|
if (Input.GetKeyDown(leanLeftKey))
|
|
|
|
|
{
|
|
|
|
|
isLeaningLeft = !isLeaningLeft;
|
|
|
|
|
isLeaningRight = false;
|
|
|
|
|
}
|
|
|
|
|
if (Input.GetKeyDown(leanRightKey))
|
|
|
|
|
{
|
|
|
|
|
isLeaningRight = !isLeaningRight;
|
|
|
|
|
isLeaningLeft = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (Input.GetKey(leanLeftKey) && !isLeaningRight)
|
|
|
|
|
{
|
|
|
|
|
isLeaningLeft = true;
|
|
|
|
|
isLeaningRight = false;
|
|
|
|
|
}
|
|
|
|
|
if (Input.GetKey(leanRightKey) && !isLeaningLeft)
|
|
|
|
|
{
|
|
|
|
|
isLeaningRight = true;
|
|
|
|
|
isLeaningLeft = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Apply the current leaning angle using the maximum leaning angle
|
|
|
|
|
currentLeaningAngle = Mathf.Clamp(currentLeaningAngle, -maxLeaningAngle, maxLeaningAngle);
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-03 16:04:59 +00:00
|
|
|
|
private void ApplyFinalMovements()
|
|
|
|
|
{
|
|
|
|
|
if (!characterController.isGrounded)
|
|
|
|
|
moveDirection.y -= gravity * Time.deltaTime;
|
|
|
|
|
|
|
|
|
|
characterController.Move(moveDirection * Time.deltaTime);
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-31 20:25:12 +00:00
|
|
|
|
private void HandleSpeedChange()
|
|
|
|
|
{
|
|
|
|
|
float scroll = Input.GetAxis("Mouse ScrollWheel");
|
|
|
|
|
|
|
|
|
|
if (scroll > 0)
|
|
|
|
|
{
|
|
|
|
|
// Increase walk speed if within the maximum limit
|
|
|
|
|
if (currentWalkSpeed < maxWalkSpeed)
|
|
|
|
|
{
|
|
|
|
|
currentWalkSpeed += walkSpeedInterval;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (scroll < 0)
|
|
|
|
|
{
|
|
|
|
|
// Decrease walk speed if within the minimum limit
|
|
|
|
|
if (currentWalkSpeed > minWalkSpeed)
|
|
|
|
|
{
|
|
|
|
|
currentWalkSpeed -= walkSpeedInterval;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update the walk speed
|
|
|
|
|
walkSpeed = currentWalkSpeed;
|
|
|
|
|
}
|
2022-10-08 02:26:09 +00:00
|
|
|
|
|
|
|
|
|
}
|