替换脚本PlayerMovement_02.cs
using System. Collections ;
using System. Collections. Generic ;
using UnityEngine ;
public class PlayerMovement_03 : MonoBehaviour
{
private float moveSpeed;
public float walkSpeed = 7 ;
public float sprintSpeed = 10 ;
public float slideSpeed = 30 ;
private float desiredMoveSpeed;
private float lastDesiredMoveSpeed;
public float speedIncreaseMultiplier = 1.5f ;
public float slopeIncreaseMultiplier = 2.5f ;
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,
sliding,
air
}
public bool sliding;
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 ( moveDirection) * 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 ( sliding)
{
state = MovementState. sliding;
if ( OnSlope ( ) && rb. velocity. y < 0.1f )
{
desiredMoveSpeed = slideSpeed;
}
else
{
desiredMoveSpeed = sprintSpeed;
}
}
else if ( Input. GetKey ( crouchKey) )
{
state = MovementState. crouching;
desiredMoveSpeed = crouchSpeed;
}
else if ( grounded && Input. GetKey ( sprintKey) )
{
state = MovementState. sprinting;
desiredMoveSpeed = sprintSpeed;
}
else if ( grounded)
{
state = MovementState. walking;
desiredMoveSpeed = walkSpeed;
}
else
{
state = MovementState. air;
}
if ( Mathf. Abs ( desiredMoveSpeed - lastDesiredMoveSpeed) > 4f && moveSpeed != 0 )
{
StopAllCoroutines ( ) ;
StartCoroutine ( SmoothlyLerpMoveSpeed ( ) ) ;
}
else
{
moveSpeed = desiredMoveSpeed;
}
lastDesiredMoveSpeed = desiredMoveSpeed;
}
public 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 ;
}
public Vector3 GetSlopeMoveDirection ( Vector3 direction)
{
return Vector3. ProjectOnPlane ( direction, slopeHit. normal) . normalized;
}
private IEnumerator SmoothlyLerpMoveSpeed ( )
{
float time = 0 ;
float difference = Mathf. Abs ( desiredMoveSpeed - moveSpeed) ;
float startValue = moveSpeed;
while ( time < difference)
{
moveSpeed = Mathf. Lerp ( startValue, desiredMoveSpeed, time / difference) ;
if ( OnSlope ( ) )
{
float slopeAngle = Vector3. Angle ( Vector3. up, slopeHit. normal) ;
float slopeAngleIncrease = 1 + ( slopeAngle / 90f ) ;
time += Time. deltaTime * speedIncreaseMultiplier * slopeIncreaseMultiplier * slopeAngleIncrease;
}
else
{
time += Time. deltaTime * speedIncreaseMultiplier;
}
yield return null ;
}
moveSpeed = desiredMoveSpeed;
}
}
新增脚本Sliding.cs
using System. Collections ;
using System. Collections. Generic ;
using UnityEngine ;
public class Sliding : MonoBehaviour
{
public Transform orientation;
public Transform playerObj;
private Rigidbody rb;
private PlayerMovement_03 pm_03;
public float maxSlideTime = 0.75f ;
public float slideForce = 200 ;
private float slideTimer;
public float slideYScale = 0.5f ;
private float startYScale;
public KeyCode slideKey = KeyCode. F;
private float h;
private float v;
private void Start ( )
{
rb = GetComponent < Rigidbody> ( ) ;
pm_03 = GetComponent < PlayerMovement_03> ( ) ;
startYScale = playerObj. localScale. y;
}
private void Update ( )
{
h = Input. GetAxisRaw ( "Horizontal" ) ;
v = Input. GetAxisRaw ( "Vertical" ) ;
if ( Input. GetKeyDown ( slideKey) && ( h != 0 || v != 0 ) )
{
StartSlide ( ) ;
}
if ( Input. GetKeyUp ( slideKey) && pm_03. sliding)
{
StopSlide ( ) ;
}
}
private void FixedUpdate ( )
{
if ( pm_03. sliding)
{
SlidingMovement ( ) ;
}
}
private void StartSlide ( )
{
pm_03. sliding = true ;
playerObj. localScale = new Vector3 ( playerObj. localScale. x, slideYScale, playerObj. localScale. z) ;
rb. AddForce ( Vector3. down * 5f , ForceMode. Impulse) ;
slideTimer = maxSlideTime;
}
private void SlidingMovement ( )
{
Vector3 inputDirection = orientation. forward * v + orientation. right * h;
if ( ! pm_03. OnSlope ( ) || rb. velocity. y > - 0.1f )
{
rb. AddForce ( inputDirection. normalized * slideForce, ForceMode. Force) ;
slideTimer -= Time. deltaTime;
}
else
{
rb. AddForce ( pm_03. GetSlopeMoveDirection ( inputDirection) * slideForce, ForceMode. Force) ;
}
if ( slideTimer <= 0 )
{
StopSlide ( ) ;
}
}
private void StopSlide ( )
{
pm_03. sliding = false ;
playerObj. localScale = new Vector3 ( playerObj. localScale. x, startYScale, playerObj. localScale. z) ;
}
}