playerMovement
unknown
csharp
6 months ago
7.5 kB
2
Indexable
using UnityEngine; public class PlayerMovementAdvanced : MonoBehaviour { [Header("Movement")] private float moveSpeed; public float walkSpeed; public float sprintSpeed; public float groundDrag; public float wallrunSpeed; public float staminaRegenRate; public float maxStaminaTime; public float currentStaminaTime; public bool staminaEmpty = false; private bool mustReleaseSprint = false; [Header("Jumping")] public float jumpForce; public float jumpCooldown; public float airMultiplier; bool readyToJump; [Header("Crouching")] public float crouchSpeed; public float crouchYScale; private float startYScale; [Header("Keybinds")] public KeyCode jumpKey = KeyCode.Space; public KeyCode sprintKey = KeyCode.LeftShift; public KeyCode crouchKey = KeyCode.LeftControl; [Header("Ground Check")] public float playerHeight; public LayerMask whatIsGround; public bool grounded; [Header("Slope Handling")] public float maxSlopeAngle; private RaycastHit slopeHit; private bool exitingSlope; public Transform orientation; float horizontalInput; float verticalInput; Vector3 moveDirection; Rigidbody rb; public MovementState state; public enum MovementState { walking, sprinting, wallrunning, crouching, air } public bool wallrunning; private void Start() { rb = GetComponent<Rigidbody>(); rb.freezeRotation = true; readyToJump = true; startYScale = transform.localScale.y; currentStaminaTime = maxStaminaTime; } private void Update() { // ground check grounded = Physics.Raycast(transform.position, Vector3.down, playerHeight * 0.5f + 0.2f, whatIsGround); MyInput(); SpeedControl(); StateHandler(); sprintReleaseCheck(); // handle drag if (grounded) rb.linearDamping = groundDrag; else rb.linearDamping = 0; } private void FixedUpdate() { MovePlayer(); } private void MyInput() { horizontalInput = Input.GetAxisRaw("Horizontal"); verticalInput = Input.GetAxisRaw("Vertical"); // when to jump if (Input.GetKey(jumpKey) && readyToJump && grounded) { readyToJump = false; Jump(); Invoke(nameof(ResetJump), jumpCooldown); } // start crouch if (Input.GetKeyDown(crouchKey)) { transform.localScale = new Vector3(transform.localScale.x, crouchYScale, transform.localScale.z); rb.AddForce(Vector3.down * 5f, ForceMode.Impulse); } // stop crouch if (Input.GetKeyUp(crouchKey)) { transform.localScale = new Vector3(transform.localScale.x, startYScale, transform.localScale.z); } } private void StateHandler() { // Mode - Wall Running if (wallrunning) { state = MovementState.wallrunning; moveSpeed = wallrunSpeed; } // Mode - Crouching else if (Input.GetKey(crouchKey)) { state = MovementState.crouching; moveSpeed = crouchSpeed; } // Mode - Sprinting else if (grounded && Input.GetKey(sprintKey) && currentStaminaTime > 0f && !staminaEmpty && !mustReleaseSprint) { state = MovementState.sprinting; moveSpeed = sprintSpeed; // Reduce stamina while sprinting currentStaminaTime -= Time.deltaTime; // Ensure stamina doesn't go below 0 if (currentStaminaTime < 0) { currentStaminaTime = 0; staminaEmpty = true; mustReleaseSprint = true; } } // Mode - Walking else if (grounded) { state = MovementState.walking; moveSpeed = walkSpeed; // Gradual stamina regeneration when NOT sprinting if (currentStaminaTime < maxStaminaTime) { currentStaminaTime += Time.deltaTime * staminaRegenRate; if (currentStaminaTime > maxStaminaTime) { currentStaminaTime = maxStaminaTime; staminaEmpty = false; } // Ensure it doesn't exceed max } } // Mode - Air else { state = MovementState.air; } print("Current State: " + state + " | Stamina: " + currentStaminaTime); } private void sprintReleaseCheck() { if (Input.GetKeyUp(sprintKey)) { mustReleaseSprint = false; } } private void MovePlayer() { // calculate movement direction moveDirection = orientation.forward * verticalInput + orientation.right * horizontalInput; // on slope if (OnSlope() && !exitingSlope) { rb.AddForce(GetSlopeMoveDirection() * moveSpeed * 20f, ForceMode.Force); if (rb.linearVelocity.y > 0) rb.AddForce(Vector3.down * 80f, ForceMode.Force); } // on ground else if (grounded) rb.AddForce(moveDirection.normalized * moveSpeed * 10f, ForceMode.Force); // in air else if (!grounded) rb.AddForce(moveDirection.normalized * moveSpeed * 10f * airMultiplier, ForceMode.Force); // turn gravity off while on slope if (!wallrunning) rb.useGravity = !OnSlope(); } private void SpeedControl() { // limiting speed on slope if (OnSlope() && !exitingSlope) { if (rb.linearVelocity.magnitude > moveSpeed) rb.linearVelocity = rb.linearVelocity.normalized * moveSpeed; } // limiting speed on ground or in air else { Vector3 flatVel = new Vector3(rb.linearVelocity.x, 0f, rb.linearVelocity.z); // limit velocity if needed if (flatVel.magnitude > moveSpeed) { Vector3 limitedVel = flatVel.normalized * moveSpeed; rb.linearVelocity = new Vector3(limitedVel.x, rb.linearVelocity.y, limitedVel.z); } } } private void Jump() { exitingSlope = true; // reset y velocity rb.linearVelocity = new Vector3(rb.linearVelocity.x, 0f, rb.linearVelocity.z); rb.AddForce(transform.up * jumpForce, ForceMode.Impulse); } private void ResetJump() { readyToJump = true; exitingSlope = false; } private bool OnSlope() { if (Physics.Raycast(transform.position, Vector3.down, out slopeHit, playerHeight * 0.5f + 0.3f)) { float angle = Vector3.Angle(Vector3.up, slopeHit.normal); return angle < maxSlopeAngle && angle != 0; } return false; } private Vector3 GetSlopeMoveDirection() { return Vector3.ProjectOnPlane(moveDirection, slopeHit.normal).normalized; } }
Editor is loading...
Leave a Comment