Проверка Animator на скрипте Unity работает только с первым объектом

Позвольте мне сначала пояснить вопрос :)

У меня есть герой и враг. Это файтинг. И у героя, и у врага есть анимации и состояния idle, block, punch и getHit в контроллере анимации. К герою и противнику прикреплены скрипты. Герой управляет игрок, а враг - ИИ.

Теперь я прикрепляю сценарий сначала к герою, а затем к противнику. Теперь, когда противник бьет и если герой не защищается, герой получает удар. Но если противник не блокирует, а герой попадает, то врага не попадает. Это потому, что скрипт был прикреплен к герою первым.

Теперь, если я удалю сценарий из обоих и сначала прикреплю сценарий врага к врагу, а затем прикреплю сценарий героя к герою. Вайдеверса верна. У врага попадания будут регистрироваться, а у героя - нет.

Я не уверен, почему это происходит, я пробовал разные вещи, но проблема все еще сохраняется.

Я также пробовал искать решение повсюду в Интернете, но ни одно из них не решило мою проблему.

Спасибо :)

ниже приведен сценарий врага, который проверяет, может ли враг получить удар

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");

        }
    }
 }

Вместо получения объекта я использовал общедоступный GameObject и прикреплял героя и врага к соответствующим классам. Но это не имеет значения.


person Siddharth Shekar    schedule 24.01.2017    source источник


Ответы (1)


Думаю, ваша проблема заключается в использовании триггеров tEnemyIsPunching и tIsPunching. Триггеры сбрасываются всякий раз, когда они вызывают переход

(см .: 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

Таким образом, Герой никогда не видит удар, потому что bIsEnemyPunching был сброшен до того, как Герой внес изменения, чтобы проверить его.

Вот почему порядок добавления скриптов имеет значение. Какой бы сценарий ни обновлялся первым, он сможет пробить, потому что второй сценарий увидит триггер до того, как он будет сброшен. Однако второй скрипт, который нужно обновить, никогда не сможет сработать, потому что триггер сбрасывается до того, как другие скрипты получат возможность обновить.

Одно из решений - проверить имя состояния анимации вместо значения триггера.

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, а затем искать все его компоненты, чтобы найти аниматора. Сделайте это один раз и сохраните результат.

person Ricky R    schedule 24.01.2017