Unity Mecanim C# 动画切换实践:实现随机播放待机动画

发布于:2025-06-13 ⋅ 阅读:(29) ⋅ 点赞:(0)

在游戏开发中,角色的动画状态管理是非常重要的一部分。Unity 的 Mecanim 状态机系统 提供了强大的功能来控制和切换角色动画。本文将通过一篇完整的 C# 脚本示例,讲解如何使用 Unity 的 Animator 实现一个简单的“随机播放待机动画”的逻辑。


效果目标

我们希望实现以下功能:

  • 当前播放默认的待机动画(例如 SiteIDE)。
  • 待机动画播放完成后,自动随机选择一个其他动画进行播放(如 Site_JiaoTanSite_JiaoTan2 等)。
  • 使用 Animator.CrossFade 实现平滑过渡,并保证动画切换流畅自然。

脚本结构概览

using UnityEngine;

[RequireComponent(typeof(Animator))]
public class MecanimRandomAnimation : MonoBehaviour
{
    public string idleStateName = "SiteIDE";
    public string[] otherAnimationNames = {
        "Site_JiaoTan",
        "Site_JiaoTan2",
        "Site_JiaoTan3",
        "Site_JiaoTan4",
        "Site_DongZhangXiWang2"
    };

    [Tooltip("过渡时间(秒)")]
    public float transitionDuration = 0.5f;

    private Animator animator;
    private int idleHash;

    void Start()
    {
        // 初始化 Animator 和动画状态哈希值
    }

    void Update()
    {
        CheckIfIdleFinished();
    }

    void CheckIfIdleFinished()
    {
        // 检测当前动画是否播放完毕
    }

    void PlayRandomAnimation()
    {
        // 随机播放其他动画
    }

    private string GetAnimatorStateName(AnimatorStateInfo stateInfo)
    {
        // 获取当前动画名称用于调试
    }
}

核心代码解析

初始化部分(Start()

我们首先获取组件并初始化相关变量:

void Start()
{
    animator = GetComponent<Animator>();
    if (animator == null)
    {
        Debug.LogError("未找到 Animator 组件!");
        return;
    }

    idleHash = Animator.StringToHash(idleStateName);
    animator.Play(idleHash, 0, 0f); // 初始播放待机动画
}

⚠️ 注意:确保挂载脚本的对象上确实有 Animator 组件。


帧更新检测(Update()

每帧调用 CheckIfIdleFinished() 方法,用于判断当前动画是否播放完成:

void Update()
{
    CheckIfIdleFinished();
}

判断动画是否播放完毕(CheckIfIdleFinished()

这是整个逻辑的核心部分,我们通过 AnimatorStateInfo 来获取当前动画的状态信息:

void CheckIfIdleFinished()
{
    AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0);

    bool isIdle = stateInfo.shortNameHash == idleHash;
    bool isFinished = stateInfo.normalizedTime >= 1.0f;
    bool notInTransition = !animator.IsInTransition(0);

    if (isIdle && isFinished && notInTransition)
    {
        PlayRandomAnimation();
    }
}
关键点说明:
  • stateInfo.normalizedTime: 归一化的播放进度,当其 ≥ 1 表示该动画已播放完一遍。
  • animator.IsInTransition(0): 判断当前是否处于动画过渡状态,避免重复触发切换。
  • stateInfo.shortNameHash: 动画状态的唯一标识符,用于高效比较。

随机播放其他动画(PlayRandomAnimation()

该方法会从 otherAnimationNames 中随机选择一个动画进行播放:

void PlayRandomAnimation()
{
    int randomIndex = Random.Range(0, otherAnimationNames.Length);
    string nextAnimName = otherAnimationNames[randomIndex];
    int nextAnimHash = Animator.StringToHash(nextAnimName);

    animator.CrossFade(nextAnimHash, transitionDuration, 0);
    animator.Play(nextAnimHash, 0, 0f); // 强制跳转
}

💡 使用 CrossFade 可以实现平滑过渡,而 Play 则强制开始播放新动画。


调试辅助函数(GetAnimatorStateName()

方便查看当前正在播放的动画名称,用于调试输出:

private string GetAnimatorStateName(AnimatorStateInfo stateInfo)
{
    foreach (string name in otherAnimationNames)
    {
        if (stateInfo.shortNameHash == Animator.StringToHash(name))
        {
            return name;
        }
    }

    if (stateInfo.shortNameHash == idleHash)
    {
        return idleStateName;
    }

    return "未知状态";
}

使用建议与优化

推荐做法:

  • 将所有动画状态统一命名规范,便于查找与调试。
  • 使用 AnimatorController 管理状态之间的过渡逻辑。
  • 如果需要循环播放某个动画,请确保其设置为 Loop Time。

进阶扩展:

  • 添加动画播放次数限制或冷却机制。
  • 结合事件系统,在动画结束时触发其他行为(如音效、粒子效果等)。
  • 使用协程替代 Update(),减少性能消耗。

总结

本文通过一个完整的 Unity 脚本示例,演示了如何利用 Mecanim 系统实现一个基于播放完成的随机动画切换机制。这个思路可以广泛应用于 NPC 角色行为、角色空闲动作、AI 动作序列等场景中。

如果你正在制作 RPG、模拟类或休闲类游戏,这样的小技巧能大大提升角色表现力和真实感!


相关资源推荐

  • Unity 官方文档 - Animator
  • Unity 动画系统教程 - Mecanim 入门
  • Unity 动画状态机设计最佳实践

如果你觉得这篇文章对你有帮助,欢迎点赞、收藏或分享给更多开发者朋友!如果你对 Unity 动画系统还有其他疑问,也欢迎留言讨论 


网站公告

今日签到

点亮在社区的每一天
去签到