在 Unity 脚本上检查 Animator 仅适用于第一个对象

Checking Animator on Unity script only work on first Object

我先解释一下问题:)

我有英雄也有敌人。这是一款格斗游戏。英雄和敌人在动画控制器中都有 idle、block、punch 和 getHit 动画和状态。英雄和敌人都附有脚本。英雄由玩家控制,然后敌人由 AI 控制。

现在我先将脚本附加到英雄,然后再附加到敌人。现在,当敌人出拳时,如果英雄没有防守,英雄就会受到打击。但是如果敌人没有阻挡并且英雄击中敌人则不会受到击中。 这是因为脚本先附在英雄身上

现在,如果我从两者中删除脚本并首先将敌人脚本附加到敌人,然后将英雄脚本附加到英雄。智慧反之亦然。在敌人身上会记录命中,在英雄身上不会记录命中。

我不确定为什么会这样,我尝试了不同的方法,但问题仍然存在。

我也尝试在网上到处寻找解决方案,但 none 解决了我的问题。

谢谢:)

下面是检查敌人是否能承受攻击的敌人脚本

void Update () {

    myTick++;
    currentTick = myTick;


    GameObject player = GameObject.Find("theDude");
    Animator pAnim = player.GetComponent<Animator>();

    //Getting Hit
    if (pAnim.GetBool("tIsPunching"))
    {
        if (anim.GetBool("bEnemyIsDefending") == false)
        {

            Debug.Log("enemy got hit");
            anim.SetTrigger("tEnemyGotHit");
            anim.SetBool("bEnemyIsDefending", true);
        }
    }
}

这是检查英雄是否可以命中的英雄脚本。

void Update () {

    totalTime += Time.deltaTime;

    GameObject enemy = GameObject.Find("Enemy");
    Animator eAnim = enemy.GetComponent<Animator>();

    //Getting Hit
    if (eAnim.GetBool("tEnemyIsPunching"))
    {
        if (anim.GetBool("bIsDefending") == false)
        {

            Debug.Log("player got hit");
            anim.SetTrigger("tGotHit");

        }
    }
 }

我以前有一个 public 游戏对象,而不是获取对象,并将英雄和敌人附加到各自的 类 中。但这没有任何区别。

我认为你的问题在于你使用触发器 tEnemyIsPunchingtIsPunching。只要触发发生转换,触发器就会重置

(参见:https://docs.unity3d.com/Manual/AnimationParameters.html)。

在您的情况下,tIsEnemyPunching 或 (tIsPunching) 在设置时在同一帧中重置。这是一个示例,说明如果先添加英雄脚本,您的游戏中的更新循环可能会是什么样子:

Hero Update()
    Check if enemy is punching
    He is not, so don't do anything

Enemy Update()
    Punch! Set 'bIsEnemyPunching' = true

Animation Update()
    bIsEnemyPunching is true so transition to the punching animation
    reset bIsEnemyPunching = false

在下一次更新中让我们看看英雄更新中发生了什么:

Hero Update()
    Check bIsEnemyPunching
    bIsEnemyPunching was reset in the previous frame, so it is false
    Since the enemy isn't punching don't do anything

所以 Hero 永远看不到拳头,因为 bIsEnemyPunching 在 Hero 进行更改以检查它之前就被重置了。

这就是添加脚本的顺序很重要的原因。无论哪个脚本首先更新都能够打孔,因为第二个脚本将在重置之前看到触发器。但是,要更新的第二个脚本将永远无法打孔,因为在其他脚本有机会更新之前触发器已重置。

一种解决方案是检查动画状态的名称而不是触发值。

static int punchStateHash = Animator.StringToHash("Punch");  
AnimatorStateInfo enemyState = eAnim.GetCurrentAnimatorStateInfo(0);

 if (enemyState.nameHash == punchStateHash){
      //The enemy is punching!
 }

或者,每当一拳被触发时,只需调用一个函数来处理正在被击打的角色。所以当敌人打英雄时,敌人的 Punch(...) 函数应该调用英雄的 TakePunch(...) (或者任何你想调用的函数)。英雄然后检查自己的状态以确定他是否正在阻塞。

补充说明

您应该避免在更新函数中使用以下代码:

GameObject player = GameObject.Find("theDude");
Animator pAnim = player.GetComponent<Animator>();

这些函数非常慢,因为 Unity 必须在所有对象中搜索名为 theDude 的对象,然后搜索它的所有组件以找到动画师。这样做一次并保存结果。