using System.Collections;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
//移动相关的参数
[Header("Movement")]
public float moveSpeed;
public float xtraSpeedCap;
public float xtraSpeedCapSlope;
public float xtraSpeedCapReal;
public float xtraSpeedCapSlopeReal;
public float slideSpeed;
private float desiredMoveSpeed;
private float lastDesiredMoveSpeed;
public float lastFallSpeed;
//强度参数
public float speedIncreaseMultiplier;
public float slopeIncreaseMultiplier;
public float groundDrag;
private float desiredDurationPlus = 0.8f;
private float elapsedPlus;
float pcntCpltPlus;
//跳跃相关的参数
public float jumpForce;
public float jumpCooldown;
public float airMarkiplier;
bool readyToJump;
//键位相关的参数
[Header("Keybinds")]
public KeyCode jumpKey = KeyCode.Space;
public KeyCode slowKey = KeyCode.LeftShift;
//检测是否站在地面的参数
[Header("Ground Check")]
public float playerHeight;
public LayerMask whatIsGroundnt;
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 Camera camme;
public FallingAcceleration fa;
public MovementState state;
public enum MovementState
{
moving,
sliding,
air
}
public bool sliding;
private void Start()
{
rb = GetComponent<Rigidbody>();
rb.freezeRotation = true;
readyToJump = true;
xtraSpeedCap = xtraSpeedCapReal;
xtraSpeedCapSlope = xtraSpeedCapSlopeReal;
}
private void Update()
{
//检测是否站在地上
grounded = Physics.Raycast(transform.position, Vector3.down, playerHeight * 0.5f + 0.3F, ~whatIsGroundnt);
MyInput();
SpeedControl();
StateHandler();
//调整阻尼
if (grounded)
rb.linearDamping = groundDrag;
else
rb.angularDamping = 0;
if (!grounded)
{
lastFallSpeed = fa.fallTimer * fa.fallAcceleration;
}
else if (grounded && !sliding)
{
lastFallSpeed = 0;
}
if (!sliding)
{
xtraSpeedCap = xtraSpeedCapReal;
xtraSpeedCapSlope = xtraSpeedCapSlopeReal;
}
else if (sliding && grounded)
{
xtraSpeedCap = xtraSpeedCapReal + (lastFallSpeed / 26f);
xtraSpeedCapSlope = xtraSpeedCapSlopeReal + (lastFallSpeed / 20f);
}
//FOV缩放
if (sliding && grounded && rb.mass == 1 || !grounded)
{
elapsedPlus += Time.deltaTime;
pcntCpltPlus = elapsedPlus / desiredDurationPlus;
camme.fieldOfView = Mathf.Lerp(PlayerPrefs.GetFloat("FOVLevel", 100f), PlayerPrefs.GetFloat("FOVLevel", 100f) + 10, pcntCpltPlus);
if (pcntCpltPlus >= 1)
{
elapsedPlus = 0;
}
}
else if (grounded && !sliding && rb.mass == 1)
{
camme.fieldOfView = PlayerPrefs.GetFloat("FOVLevel", 100f);
}
}
private void FixedUpdate()
{
MovePlayer();
}
private void MyInput()
{
horizontalInput = Input.GetAxisRaw("Horizontal");
verticalInput = Input.GetAxisRaw("Vertical");
//检查是否可以跳跃
if (grounded && sliding && Input.GetKey(jumpKey) && readyToJump)
{
readyToJump = false;
Jump();
rb.AddForce(moveDirection * (jumpForce), ForceMode.Impulse);
Invoke(nameof(ResetJump), jumpCooldown);
}
else if (Input.GetKey(jumpKey) && readyToJump && grounded)
{
readyToJump = false;
Jump();
Invoke(nameof(ResetJump), jumpCooldown);
}
}
private void StateHandler()
{
//检测运动状态
if (sliding)
{
state = MovementState.sliding;
if (OnSlope() && rb.linearVelocity.y < 0.1f)
desiredMoveSpeed = slideSpeed;
else
desiredMoveSpeed = moveSpeed;
}
//运动状态
else if (grounded)
{
state = MovementState.moving;
desiredMoveSpeed = moveSpeed;
}
//空中状态
else
{
state = MovementState.air;
}
//检查是否有速度改变
if (Mathf.Abs(desiredMoveSpeed - lastDesiredMoveSpeed) > 4f && moveSpeed != 0 && !sliding && (xtraSpeedCap != xtraSpeedCapReal))
{
StopAllCoroutines();
StartCoroutine(SmoothlyLerpMoveSpeed());
}
}
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;
}
private void MovePlayer()
{
//设置移动指向
moveDirection = orientation.forward * verticalInput + orientation.right * horizontalInput;
//设置重力
if (Input.GetKey(slowKey) && grounded && !sliding && !OnSlope())
{
rb.mass = 1.3f;
}
else if (Input.GetKey(slowKey) && grounded && !sliding && OnSlope())
{
rb.mass = 5f;
}
else
{
rb.mass = 1;
}
//倾斜处理
if (OnSlope() && !exitingSlope)
{
rb.AddForce(GetSlopeMoveDirection(moveDirection) * moveSpeed * 20f, ForceMode.Force);
if (rb.linearVelocity.y != 0)
rb.AddForce(Vector3.down * 200f, ForceMode.Force);
}
//在地面上处理
else if (grounded)
rb.AddForce(moveDirection.normalized * moveSpeed * 10f, ForceMode.Force);
//在空中处理
else if (!grounded)
rb.AddForce(moveDirection.normalized * moveSpeed * 10f * airMarkiplier, ForceMode.Force);
//取消重力
rb.useGravity = !OnSlope();
}
private void SpeedControl()
{
//限速
if (OnSlope() && !exitingSlope)
{
if (rb.linearVelocity.magnitude > (moveSpeed + xtraSpeedCapSlope))
rb.linearVelocity = rb.linearVelocity.normalized * moveSpeed;
}
else
{
Vector3 flatVel = new Vector3(rb.linearVelocity.x, 0f, rb.linearVelocity.z);
//限速
if (flatVel.magnitude > (moveSpeed + xtraSpeedCap))
{
Vector3 limitedVel = flatVel.normalized * moveSpeed;
rb.linearVelocity = new Vector3(limitedVel.x, rb.linearVelocity.y, limitedVel.z);
}
}
}
private void Jump()
{
exitingSlope = true;
//清除y速度
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;
}
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 < maxSlopeAngle && angle != 0;
}
return false;
}
public Vector3 GetSlopeMoveDirection(Vector3 direction)
{
return Vector3.ProjectOnPlane(direction, slopeHit.normal).normalized;
}
}
评论 (0)