直接修改或者替换PlayerMovement_01.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement_02 : MonoBehaviour
{
private float moveSpeed;
public float walkSpeed = 7;
public float sprintSpeed = 10;
public float groundDrag = 5;
public float playerHeight = 2;
public LayerMask whatIsGround;
private bool grounded;
public float jumpForce = 6;
public float jumpCooldown = 0.25f;
public float airMultiplier = 0.4f;
private bool readyToJump = true;
public float crouchSpeed = 3.5f;
public float crouchYScale = 0.5f;
private float startYScale;
public float maxSlopAngle = 40;
private RaycastHit slopeHit;
private bool exitingSlope = true;
public KeyCode jumpKey = KeyCode.Space;
public KeyCode sprintKey = KeyCode.LeftShift;
public KeyCode crouchKey = KeyCode.LeftControl;
public Transform orientation;
private float h;
private float v;
private Vector3 moveDirection;
private Rigidbody rb;
public MovementState state;
public enum MovementState
{
walking,
sprinting,
crouching,
air
}
private void Start()
{
rb = GetComponent<Rigidbody>();
rb.freezeRotation = true;
startYScale = transform.localScale.y;
}
private void Update()
{
grounded = Physics.Raycast(transform.position, Vector3.down, playerHeight * 0.5f + 0.2f, whatIsGround);
MyInput();
SpeedControl();
StateHandler();
if (grounded)
rb.drag = groundDrag;
else
rb.drag = 0;
}
private void FixedUpdate()
{
MovePlayer();
}
private void MyInput()
{
h = Input.GetAxisRaw("Horizontal");
v = Input.GetAxisRaw("Vertical");
if (Input.GetKey(jumpKey) && readyToJump && grounded)
{
readyToJump = false;
Jump();
Invoke(nameof(ResetJump), jumpCooldown);
}
if (Input.GetKeyDown(crouchKey))
{
transform.localScale = new Vector3(transform.localScale.x, crouchYScale, transform.localScale.z);
rb.AddForce(Vector3.down * 5f, ForceMode.Impulse);
}
if (Input.GetKeyUp(crouchKey))
{
transform.localScale = new Vector3(transform.localScale.x, startYScale, transform.localScale.z);
}
}
private void MovePlayer()
{
moveDirection = orientation.forward * v + orientation.right * h;
if (OnSlope() && !exitingSlope)
{
rb.AddForce(GetSlopeMoveDirection() * moveSpeed * 20f, ForceMode.Force);
if (rb.velocity.y > 0)
{
rb.AddForce(Vector3.down * 80f, ForceMode.Force);
}
}
else if (grounded)
{
rb.AddForce(moveDirection.normalized * moveSpeed * 10f, ForceMode.Force);
}
else if (!grounded)
{
rb.AddForce(moveDirection.normalized * moveSpeed * 10f * airMultiplier, ForceMode.Force);
}
rb.useGravity = !OnSlope();
}
private void SpeedControl()
{
if (OnSlope() && !exitingSlope)
{
if (rb.velocity.magnitude > moveSpeed)
{
rb.velocity = rb.velocity.normalized * moveSpeed;
}
}
else
{
Vector3 flatVel = new Vector3(rb.velocity.x, 0f, rb.velocity.z);
if (flatVel.magnitude > moveSpeed)
{
Vector3 limitedVel = flatVel.normalized * moveSpeed;
rb.velocity = new Vector3(limitedVel.x, rb.velocity.y, limitedVel.z);
}
}
}
private void Jump()
{
exitingSlope = true;
rb.velocity = Vector3.zero;
rb.AddForce(transform.up * jumpForce, ForceMode.Impulse);
}
private void ResetJump()
{
readyToJump = true;
exitingSlope = false;
}
private void StateHandler()
{
if (grounded && Input.GetKey(sprintKey))
{
state = MovementState.sprinting;
moveSpeed = sprintSpeed;
}
else if (grounded)
{
state = MovementState.walking;
moveSpeed = walkSpeed;
}
else
{
state = MovementState.air;
}
if (Input.GetKey(crouchKey))
{
state = MovementState.crouching;
moveSpeed = crouchSpeed;
}
}
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 < maxSlopAngle && angle != 0;
}
return false;
}
private Vector3 GetSlopeMoveDirection()
{
return Vector3.ProjectOnPlane(moveDirection, slopeHit.normal).normalized;
}
}