You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity:如何在StateMachineBehaviour中实现状态延迟与Boss攻击冷却?

解决方案:实现Boss攻击后Run状态冷却

核心思路

StateMachineBehaviour 本身不是 MonoBehaviour 子类,无法直接启动协程。我们需要借助挂载在 Boss 对象上的 MonoBehaviour(即你的 Boss.cs 脚本)来管理冷却逻辑,同时在状态机中判断冷却状态,限制攻击触发。


步骤1:在Boss主脚本中添加冷却逻辑

打开你的 Boss.cs(挂载在Boss对象上的 MonoBehaviour 脚本),添加以下代码:

public bool isAttackOnCooldown = false;
public float attackCooldown = 2f; // 冷却时长,可在Inspector面板调整
public Transform player; // 缓存Player引用

private void Start()
{
    player = GameObject.FindGameObjectWithTag("Player").transform;
}

// 启动冷却协程的方法
public void StartAttackCooldown()
{
    if (!isAttackOnCooldown)
    {
        StartCoroutine(AttackCooldownCoroutine());
    }
}

// 冷却协程
private IEnumerator AttackCooldownCoroutine()
{
    isAttackOnCooldown = true;
    yield return new WaitForSeconds(attackCooldown);
    isAttackOnCooldown = false;
}

步骤2:修改Run状态的StateMachineBehaviour

更新你当前的Run状态行为脚本,添加冷却判断逻辑:

private Transform player;
private Rigidbody2D rb;
private Boss boss;
private bool switchAttack = false;

override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
    // 复用Boss脚本缓存的引用,避免重复查找
    boss = animator.GetComponent<Boss>();
    rb = animator.GetComponent<Rigidbody2D>();
    player = boss.player;
}

override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
    boss.LookAtPlayer();

    Vector2 target = new Vector2(player.position.x, rb.position.y);
    Vector2 newPos = Vector2.MoveTowards(rb.position, target, speed * Time.fixedDeltaTime);
    rb.MovePosition(newPos);

    // 仅当不在冷却范围内,且距离满足时才触发攻击
    if (!boss.isAttackOnCooldown && Vector2.Distance(player.position, rb.position) <= attackRange)
    {
        animator.SetTrigger("Attack");
        animator.SetBool("AttackSwitch", switchAttack);
    }
}

override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
    animator.ResetTrigger("Attack");
    switchAttack = !animator.GetBool("AttackSwitch");
}

步骤3:在Attack状态添加冷却触发逻辑

创建一个新的 StateMachineBehaviour 脚本(比如命名为 AttackExitCooldown),用于在攻击结束时启动冷却:

using UnityEngine;

public class AttackExitCooldown : StateMachineBehaviour
{
    private Boss boss;

    override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        boss = animator.GetComponent<Boss>();
    }

    override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        // 攻击动画结束时,启动冷却
        boss.StartAttackCooldown();
    }
}

将这个脚本添加到Animator中所有攻击状态(比如Attack1、Attack2)的Behaviour列表里。


为什么之前的方法失败?

  1. StateMachineBehaviour 不是 MonoBehaviour,无法直接调用 StartCoroutine,必须通过同一对象上的 MonoBehaviour(如你的Boss.cs)来启动。
  2. 你之前的代码中未正确赋值 monoBehaviour 变量,导致协程无法启动。
  3. 重复在协程中获取组件是冗余操作,应该复用已缓存的引用。

内容的提问来源于stack exchange,提问作者Alon Belkin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 19:20:01