aboutsummaryrefslogtreecommitdiff
path: root/Assets/Scripts/AnimatorHandler.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Assets/Scripts/AnimatorHandler.cs')
-rw-r--r--Assets/Scripts/AnimatorHandler.cs124
1 files changed, 96 insertions, 28 deletions
diff --git a/Assets/Scripts/AnimatorHandler.cs b/Assets/Scripts/AnimatorHandler.cs
index df1f1f1..deae0ac 100644
--- a/Assets/Scripts/AnimatorHandler.cs
+++ b/Assets/Scripts/AnimatorHandler.cs
@@ -5,107 +5,175 @@ using UnityEngine;
namespace DS
{
+ /// <summary>
+ /// 动画处理器 - 负责管理角色动画参数的更新、根运动(Root Motion)的提取,
+ /// 以及角色旋转状态的控制。
+ /// </summary>
public class AnimatorHandler : MonoBehaviour
{
- public PlayerLocomotion playerLocomotion;
- public Animator animator;
- private int _vertical;
- private int _horizontal;
- public bool canRotate;
+ [Header("组件引用")]
+ public PlayerLocomotion playerLocomotion; // 玩家移动控制器引用,用于传递根运动数据
+ public Animator animator; // 动画器组件引用
+ [Header("动画参数哈希")]
+ private int _vertical; // "Vertical" 动画参数的哈希值,用于高效设置动画参数
+ private int _horizontal; // "Horizontal" 动画参数的哈希值
+
+ [Header("旋转状态")]
+ public bool canRotate; // 是否允许角色旋转,在动画事件中控制
+
+ /// <summary>
+ /// 初始化函数 - 获取 Animator 组件并计算动画参数的哈希值。
+ /// 哈希值用于替代字符串名称,提高性能。
+ /// </summary>
public void Initialize()
{
+ // 获取当前 GameObject 上的 Animator 组件
animator = GetComponent<Animator>();
+
+ // 使用 Animator.StringToHash 将字符串参数名转换为整数哈希值
+ // 这样在 SetFloat 时使用哈希值比使用字符串更高效
_vertical = Animator.StringToHash("Vertical");
_horizontal = Animator.StringToHash("Horizontal");
}
+ /// <summary>
+ /// 更新动画参数值 - 将输入的移动数值映射为动画混合树使用的离散值。
+ /// 输入值范围通常为 -1 到 1,将其量化为 -1, -0.5, 0, 0.5, 1 五个档位,
+ /// 以实现从慢走到快跑的平滑过渡。
+ /// </summary>
+ /// <param name="verticalMovement">垂直方向的移动输入(前进/后退),范围 -1 ~ 1</param>
+ /// <param name="horizontalMovement">水平方向的移动输入(左移/右移),范围 -1 ~ 1</param>
public void UpdateAnimatorValues(float verticalMovement, float horizontalMovement)
{
- #region Vertical
+ #region Vertical — 垂直方向(前进/后退)的动画参数处理
- float v = 0;
+ float v = 0; // 存储映射后的垂直动画参数值
+ // 判断垂直移动输入,将其量化为几档:
+ // 0~0.55 之间视为慢速行走(0.5),大于 0.55 视为奔跑(1)
+ // 负值同理,处理后退动作
if (verticalMovement > 0 && verticalMovement < 0.55f)
{
- v = 0.5f;
+ v = 0.5f; // 慢速前进
}
else if(verticalMovement > 0.55f)
{
- v = 1;
+ v = 1; // 快速前进/奔跑
}
else if (verticalMovement < 0 && verticalMovement > -0.55f)
{
- v = -0.5f;
+ v = -0.5f; // 慢速后退
}
else if(verticalMovement < -0.55f)
{
- v = -1;
+ v = -1; // 快速后退
}
else
{
- v = 0;
+ v = 0; // 无输入或死区范围内,保持静止
}
-
+
#endregion
-
- #region Horizontal
- float h = 0;
+ #region Horizontal — 水平方向(左/右)的动画参数处理
+
+ float h = 0; // 存储映射后的水平动画参数值
+ // 同样将水平移动输入量化为几档,用于控制侧移或转身动画
if (horizontalMovement > 0 && horizontalMovement < 0.55f)
{
- h = 0.5f;
+ h = 0.5f; // 慢速向右
}
else if(horizontalMovement > 0.55f)
{
- h = 1;
+ h = 1; // 快速向右
}
else if (horizontalMovement < 0 && horizontalMovement > -0.55f)
{
- h = -0.5f;
+ h = -0.5f; // 慢速向左
}
else if(horizontalMovement < -0.55f)
{
- h = -1;
+ h = -1; // 快速向左
}
else
{
- h = 0;
+ h = 0; // 无输入或死区范围内,保持静止
}
-
+
#endregion
-
- animator.SetFloat(_vertical,v,0.1f,Time.deltaTime);
- animator.SetFloat(_horizontal,h,0.1f,Time.deltaTime);
+
+ // 将计算后的参数值设置到 Animator 中
+ // 第三个参数 dampTime 为 0.1f,表示在 0.1 秒内平滑过渡到目标值
+ // 第四个参数 deltaTime 用于确保平滑速度与帧率无关
+ animator.SetFloat(_vertical, v, 0.1f, Time.deltaTime);
+ animator.SetFloat(_horizontal, h, 0.1f, Time.deltaTime);
}
+ /// <summary>
+ /// 动画事件回调 - 允许角色在动画的特定帧开始旋转。
+ /// 通常在动画的某个时间点(如转身动画的起始帧)由动画事件调用。
+ /// </summary>
public void CanRotate()
{
- canRotate = true;
+ canRotate = true; // 启用旋转
}
+ /// <summary>
+ /// 动画事件回调 - 停止角色的旋转。
+ /// 通常在动画的某个时间点(如转身动画的结束帧)由动画事件调用,
+ /// 防止角色在不需要旋转时继续旋转。
+ /// </summary>
public void StopRotation()
{
- canRotate = false;
+ canRotate = false; // 禁用旋转
}
+ /// <summary>
+ /// MonoBehaviour 生命周期函数 - 在 Animator 更新动画时每帧调用。
+ /// 用于处理根运动(Root Motion)数据,将动画驱动的位移传递给 PlayerLocomotion。
+ /// 需要勾选 Animator 组件的"Apply Root Motion"选项才能触发此回调。
+ /// </summary>
private void OnAnimatorMove()
{
+ // 获取当前帧的根运动位移向量
var rootMotion = GetRootMotion();
+
+ // 输出调试日志,用于查看根运动数据
Debug.Log(rootMotion);
+
+ // 将根运动数据传递给 PlayerLocomotion 组件
+ // PlayerLocomotion 会将这些位移应用到角色控制器上
playerLocomotion.rootMotion = rootMotion;
}
+ /// <summary>
+ /// 编辑器辅助函数 - 在 Scene 视图中绘制调试线条,
+ /// 可视化显示根运动的方向和大小(放大 2 倍以便观察)。
+ /// 仅在编辑器中有效,不会影响运行时性能。
+ /// </summary>
private void OnDrawGizmos()
{
+ // 从角色当前位置绘制一条线到 当前位置 + 根运动方向 * 2
Gizmos.DrawLine(transform.position, transform.position + GetRootMotion() * 2f);
}
+ /// <summary>
+ /// 提取根运动向量 - 从 Animator 的当前速度中提取水平方向上的位移,
+ /// 忽略垂直方向(Y 轴)的运动。
+ /// 这样可以防止动画中的微小垂直位移影响角色位置(如地面抖动)。
+ /// </summary>
+ /// <returns>返回一个 Vector3,表示投影到水平平面上的根运动位移</returns>
private Vector3 GetRootMotion()
{
- // 我们先假定 地板永远是朝上的
+ // 假定地面法线始终朝上(即世界坐标的 Y 轴方向)
+ // 注意:如果角色在斜坡上运动,此处需要根据地面法线动态调整
var normalVector = Vector3.up;
+
+ // 将 animator.velocity(动画驱动的速度向量)投影到法线定义的平面上
+ // Vector3.ProjectOnPlane 会去除向量中沿法线方向的分量
+ // 这样只保留水平方向的位移,避免 Y 轴上的微小波动影响角色位置
return Vector3.ProjectOnPlane(animator.velocity, normalVector);
}
}