aboutsummaryrefslogtreecommitdiff
path: root/Assets/Scripts/PlayerLocomotion.cs
diff options
context:
space:
mode:
authorWeicao-CatilGrass <1992414357@qq.com>2026-05-22 12:40:52 +0800
committerWeicao-CatilGrass <1992414357@qq.com>2026-05-22 12:40:52 +0800
commit5360e988fa7c47da8d58ee3a25a7ed92fd700a57 (patch)
tree15d96f93bf5fe95ad80a6208d024288e3494dc8c /Assets/Scripts/PlayerLocomotion.cs
parent98fc0175e3f614153fe201c9fcea693611fb4eed (diff)
让DeepSeek添加详尽的注释
Diffstat (limited to 'Assets/Scripts/PlayerLocomotion.cs')
-rw-r--r--Assets/Scripts/PlayerLocomotion.cs166
1 files changed, 140 insertions, 26 deletions
diff --git a/Assets/Scripts/PlayerLocomotion.cs b/Assets/Scripts/PlayerLocomotion.cs
index 9f058b0..8b77c06 100644
--- a/Assets/Scripts/PlayerLocomotion.cs
+++ b/Assets/Scripts/PlayerLocomotion.cs
@@ -4,110 +4,224 @@ using System.Collections.Generic;
using Unity.Mathematics;
using UnityEngine;
-
namespace DS
{
+ /// <summary>
+ /// 玩家角色移动/旋转控制器
+ /// 负责处理玩家的移动、旋转,并与输入系统、动画系统、物理系统进行交互
+ /// </summary>
public class PlayerLocomotion : MonoBehaviour
{
- // 是否使用根动画
+ // ============================================================
+ // 根运动混合参数
+ // ============================================================
+ /// <summary>
+ /// 根运动(Root Motion)与程序化移动的混合比例。
+ /// 0 = 完全使用程序化移动(手动计算位移),
+ /// 1 = 完全使用动画中的根运动(由动画驱动位移)。
+ /// 建议在跑步、行走等需要动画精细控制位移时使用根运动;
+ /// 在需要响应式操控(如闪避、冲刺)时可降低此值。
+ /// </summary>
[Range(0, 1)] public float rootMotionBlending = 1f;
+ /// <summary>
+ /// 便捷属性:将 rootMotionBlending 映射为布尔值。
+ /// true = 使用根运动(blending > 0.5),
+ /// false = 使用程序化移动(blending <= 0.5)。
+ /// </summary>
public bool usingRootMotion
{
get => rootMotionBlending > 0.5f;
set => rootMotionBlending = value ? 0 : 1;
}
-
- [HideInInspector] public Vector3 rootMotion;
- private Transform _cameraObject; //存储Camera的位置
- private InputHandler _inputHandler;
- private Vector3 _moveDirection;
+ // ============================================================
+ // 公开字段
+ // ============================================================
+ /// <summary>
+ /// 当前帧从动画中提取的根运动位移向量(由 AnimatorHandler 提供)。
+ /// 单位:米/帧。
+ /// </summary>
+ [HideInInspector] public Vector3 rootMotion;
+
+ /// <summary>
+ /// 当前角色的 Transform 引用(缓存避免重复查找)。
+ /// </summary>
[HideInInspector] public Transform myTransform;
+
+ /// <summary>
+ /// 动画处理器引用(负责驱动 Animator 参数和根运动提取)。
+ /// </summary>
[HideInInspector] public AnimatorHandler animatorHandler;
+ /// <summary>
+ /// 角色的 Rigidbody 组件引用(用于物理驱动移动)。
+ /// 使用 new 关键字隐藏父类 Rigidbody 字段以避免混淆。
+ /// </summary>
public new Rigidbody rigidbody;
- public GameObject normalCamera; //引用Camera
-
- [Header("Stats")]
- [SerializeField] private float movementSpeed = 5;
- [SerializeField] private float rotationSpeed = 10;
+ /// <summary>
+ /// 常规第三人称摄像机对象的引用(用于旋转跟随等逻辑)。
+ /// </summary>
+ public GameObject normalCamera;
+
+ // ============================================================
+ // 私有字段
+ // ============================================================
+ private Transform _cameraObject; // 主摄像机的 Transform 缓存
+ private InputHandler _inputHandler; // 输入处理器引用
+ private Vector3 _moveDirection; // 计算出的移动方向向量
+ private Vector3 _normalVector; // 地面法线向量(用于投影移动方向到地面)
+ private Vector3 _targetPosition; // 目标位置(当前未使用,保留备用)
+
+ // ============================================================
+ // 参数配置
+ // ============================================================
+ [Header("Stats")]
+ [SerializeField] private float movementSpeed = 5; // 移动速度(单位:米/秒)
+ [SerializeField] private float rotationSpeed = 10; // 旋转速度(单位:度/秒,实际用于 Slerp 插值)
+
+ // ============================================================
+ // 初始化
+ // ============================================================
private void Start()
{
+ // 获取并缓存 Rigidbody 组件
rigidbody = GetComponent<Rigidbody>();
+
+ // 获取并缓存输入处理器
_inputHandler = GetComponent<InputHandler>();
+
+ // 在子物体中查找 AnimatorHandler 组件并缓存
animatorHandler = GetComponentInChildren<AnimatorHandler>();
+
+ // 缓存主摄像机的 Transform
_cameraObject = Camera.main.transform;
+
+ // 缓存当前物体的 Transform
myTransform = transform;
+
+ // 初始化 AnimatorHandler(例如获取 Animator 组件引用等)
animatorHandler.Initialize();
}
+ // ============================================================
+ // 每帧更新(使用 Update 处理移动逻辑,因为需要与输入同步)
+ // ============================================================
private void Update()
{
UpdateCharacterMovement();
}
+ // ============================================================
+ // 固定更新(当前未使用,但保留以备未来物理相关逻辑)
+ // ============================================================
private void FixedUpdate()
{
-
+ // 当前未在此处处理逻辑
+ // 若需要基于物理的移动,可将 rigidbody.velocity 赋值移到这里
}
+ // ============================================================
+ // 角色移动更新(核心逻辑)
+ // ============================================================
private void UpdateCharacterMovement()
{
- float delta = Time.deltaTime;
+ float delta = Time.deltaTime; // 获取帧时间
+
+ // 处理输入(读取水平/垂直输入值)
_inputHandler.TickInput(delta);
+ // ----------------------------------------------------------
+ // 1. 计算移动方向(基于摄像机朝向)
+ // ----------------------------------------------------------
+ // 前方向量 = 摄像机正方向 * 垂直输入(W/S)
_moveDirection = _cameraObject.forward * _inputHandler.vertical;
+ // 侧方向量 = 摄像机右方向 * 水平输入(A/D)
_moveDirection += _cameraObject.right * _inputHandler.horizontal;
+ // 归一化,确保对角线移动时速度不叠加(保持长度 1)
_moveDirection.Normalize();
+ // 将 y 分量置 0,确保移动只在水平面上
_moveDirection.y = 0;
+ // ----------------------------------------------------------
+ // 2. 应用移动速度
+ // ----------------------------------------------------------
float speed = movementSpeed;
- _moveDirection *= speed;
-
+ _moveDirection *= speed; // 现在 _moveDirection 是速度向量(单位:米/秒)
+
+ // ----------------------------------------------------------
+ // 3. 混合根运动与程序化移动
+ // ----------------------------------------------------------
+ // 根据 rootMotionBlending 在根运动位移和程序化速度之间做线性插值
var baseVelocity = Vector3.Lerp(rootMotion, _moveDirection, rootMotionBlending);
+
+ // 将速度向量投影到地面法线平面上(防止角色飞起或陷入地面)
Vector3 projectedVelocity = Vector3.ProjectOnPlane(baseVelocity, _normalVector);
+
+ // 设置 Rigidbody 速度(物理驱动移动)
rigidbody.velocity = projectedVelocity;
-
- animatorHandler.UpdateAnimatorValues(_inputHandler.moveAmount,0);
+ // ----------------------------------------------------------
+ // 4. 更新动画参数
+ // ----------------------------------------------------------
+ // 将玩家的移动量(0~1)传递给 Animator,用于混合行走/奔跑动画
+ animatorHandler.UpdateAnimatorValues(_inputHandler.moveAmount, 0);
+
+ // ----------------------------------------------------------
+ // 5. 处理旋转(仅在允许旋转时执行)
+ // ----------------------------------------------------------
if (animatorHandler.canRotate)
{
HandleRotation(delta);
}
}
+ // ============================================================
+ // 移动与旋转相关方法
+ // ============================================================
#region Movement
- private Vector3 _normalVector;
- private Vector3 _targetPosition;
-
+ /// <summary>
+ /// 处理角色旋转逻辑。
+ /// 根据输入方向和摄像机朝向,平滑旋转角色面向移动方向。
+ /// </summary>
+ /// <param name="delta">帧时间(秒)</param>
private void HandleRotation(float delta)
{
- Vector3 targetDir = Vector3.zero;
+ Vector3 targetDir = Vector3.zero; // 目标朝向向量
+ // 注意:当前未使用 moveOverride,保留备用
float moveOverride = _inputHandler.moveAmount;
+ // ----------------------------------------------------------
+ // 1. 根据输入计算目标朝向
+ // ----------------------------------------------------------
+ // 目标朝向 = 摄像机正方向 * 垂直输入 + 摄像机右方向 * 水平输入
targetDir = _cameraObject.forward * _inputHandler.vertical;
targetDir += _cameraObject.right * _inputHandler.horizontal;
+ // 归一化并置平 Y 轴
targetDir.Normalize();
targetDir.y = 0;
+ // 如果没有输入(目标方向为零向量),则保持当前面向不变
if (targetDir == Vector3.zero)
{
targetDir = myTransform.forward;
}
- float rs = rotationSpeed;
- Quaternion tr = Quaternion.LookRotation(targetDir);
+ // ----------------------------------------------------------
+ // 2. 通过 Slerp 平滑旋转至目标方向
+ // ----------------------------------------------------------
+ float rs = rotationSpeed; // 旋转速度
+ Quaternion tr = Quaternion.LookRotation(targetDir); // 目标旋转四元数
+ // 使用球形插值(Slerp)实现平滑旋转
Quaternion targetRotation = Quaternion.Slerp(myTransform.rotation, tr, rs * delta);
+ // 应用旋转
myTransform.rotation = targetRotation;
}
-
#endregion
}
}
-