玩家状态脚本:
using UnityEditor.UI;
using UnityEngine;
// 基类,各个状态都继承这个类
public abstract class PlayerState
{
protected PlayerController controller;
public PlayerState(PlayerController controller)
{
this.controller = controller;
}
// 在进入状态时触发
public virtual void Enter() { }
// 在每个_frame更新时触发,状态可能会切换
public virtual void Update() { }
// 每个fixedupdate
public virtual void FixedUpdate() { }
// 离开状态时触发
public virtual void Exit() { }
}
// 反转运动状态
protected void ChangeToIdleCondition()
{
// 如果没有移动输入,切换到 idle状态
if (controller.GetMoveInput().magnitude < 0.1)
{
controller.ChangeState(new IdleState(controller));
}
}
// 反转运动状态
protected void ChangeToMoveCondition()
{
// 如果有移动输入且有地面
if (controller.GetMoveInput().magnitude > 0f && controller.IsGrounded())
{
controller.ChangeState(new MoveState(controller));
}
}
// 反转跳跃状态
protected void ChangeToJumpCondition()
{
// 如果有跳跃输入且有地面
if (controller.GetJumpInput() && controller.IsGrounded())
{
controller.ChangeState(new JumpState(controller));
}
}
// 执行运动动作
protected void MovePlayer()
{
// 当前速度
float currentSpeed = controller.GetSprintInput() ? controller.GetPlayerSprintSpeed() : controller.GetPlayerSpeed();
// 得到摄像机的变换
Transform cameraTransform = controller.GetCameraTransform();
// 得到前方和右方方向
Vector3 cameraForward = cameraTransform.forward;
Vector3 cameraRight = cameraTransform.right;
// 将y设置为0
cameraForward.y = 0f;
cameraRight.y = 0f;
// 正规化
cameraForward.Normalize();
cameraRight.Normalize();
// 移动输入
Vector2 moveInput = controller.GetMoveInput();
// 计算移动方向
Vector3 moveDirection = (cameraForward * moveInput.y + cameraRight * moveInput.x).normalized;
// 移动物体
controller.GetRigidbody().linearVelocity = new Vector3(moveDirection.x * currentSpeed, controller.GetRigidbody().linearVelocity.y, moveDirection.z * currentSpeed);
}
protected void ApplyDownwardsForce()
{
// 如果没有地面
if (!controller.IsGrounded())
{
// 向下施加力
controller.GetRigidbody().AddForce(Vector3.down * controller.GetPlayerDownwardsForce());
}
}
}
// 空闲状态
public class IdleState : PlayerState
{
public IdleState(PlayerController controller) : base(controller) { }
// 进入时触发
public override void Enter()
{
// 停止运动
controller.GetRigidbody().linearVelocity = [Vector3.zero];
}
// 每个_frame更新时触发
public override void Update()
{
// 反转运动状态和跳跃状态
ChangeToMoveCondition();
ChangeToJumpCondition();
}
// 每个fixedupdate
public override void FixedUpdate()
{
// 向下施加力
ApplyDownwardsForce();
}
}
// 移动状态
public class MoveState : PlayerState
{
public MoveState(PlayerController controller) : base(controller) { }
// 每个_frame更新时触发
public override void Update()
{
// 反转运动状态和跳跃状态
ChangeToIdleCondition();
ChangeToJumpCondition();
}
// 每个fixedupdate
public override void FixedUpdate()
{
// 执行运动动作
MovePlayer();
// 向下施加力
ApplyDownwardsForce();
}
}
// 跳跃状态
public class JumpState : PlayerState
{
public JumpState(PlayerController controller) : base(controller) { }
// 进入时触发
public override void Enter()
{
// 应用跳跃力
controller.GetRigidbody().linearVelocity = new Vector3(controller.GetRigidbody().linearVelocity.x, controller.GetPlayerJumpHeight(), controller.GetRigidbody().linearVelocity.z);
}
// 每个_frame更新时触发
public override void Update()
{
// 如果有地面
if (controller.IsGrounded())
{
// 反转运动状态和跳跃状态
ChangeToIdleCondition();
ChangeToMoveCondition();
}
}
// 每个fixedupdate
public override void FixedUpdate()
{
// 执行运动动作
MovePlayer();
}
}
玩家控制器脚本:
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerController : MonoBehaviour
{
// movement
[Header("Movement Settings")]
public float playerSpeed = 5f;
public float playerSprintSpeed = 10f;
private float playerDownwardsForce = 50f;
private float playerJumpHeight = 10f;
// ground check
[Header("Ground Check Settings")]
public Transform groundCheck;
public LayerMask groundLayer;
[SerializeField] private float groundCheckRadius = 0.2f;
// camera
[Header("Camera")]
public Transform orientation;
// input
PlayerInput playerInput;
InputAction moveAction;
Rigidbody rb;
bool isGrounded;
Vector2 moveInput;
// state machine
private PlayerState currentState;
void Start()
{
// 初始化变量...
rb = GetComponent<Rigidbody>();
playerInput = GetComponent<PlayerInput>();
moveAction = playerInput.actions.FindAction("Movement");
// 初始化为Idle状态
ChangeState(new IdleState(this));
}
void Update()
{
// 读取输入
if (moveAction != null)
{
moveInput = moveAction.ReadValue<Vector2>();
}
// 地面检测
isGrounded = Physics.Raycast(groundCheck.position, Vector3.down, groundCheckRadius);
// 呼叫当前状态的Update
currentState.Update();
}
private void FixedUpdate()
{
// 呼叫当前状态的FixedUpdate
currentState.FixedUpdate();
}
// state machine core
public void ChangeState(PlayerState newState)
{
// 离开当前状态
currentState.Exit();
// 更新当前状态
currentState = newState;
currentState.Enter();
}
// public getters
public Vector2 GetMoveInput() => moveInput;
public bool IsGrounded() => isGrounded;
public Rigidbody GetRigidbody() => rb;
public Transform GetCameraTransform() => orientation;
public Transform GetPlayerTransform() => transform;
public float GetPlayerSpeed() => playerSpeed;
public float GetPlayerSprintSpeed() => playerSprintSpeed;
public float GetPlayerDownwardsForce() => playerDownwardsForce;
public float GetPlayerJumpHeight() => playerJumpHeight;
public bool GetSprintInput() => playerInput.actions.FindAction("Sprinting").ReadValue<float>() == 1f;
public bool GetJumpInput() => playerInput.actions.FindAction("Jumping").ReadValue<float>() == 1f;
}
评论 (0)