При запуске игры в Unity не воспроизводится анимация, которую я сделал

120
22 марта 2021, 05:30

Делаю игру по англоязычному туториалу, все "скопировал" правильно, но что-то не работает. https://pixelnest.io/tutorials/2d-game-unity/animations-2/ это тот самый туториал. Ну вот всё скопировал как надо, но не работает. Единственное отличие от туториала что в окне Аниматора у меня ещё есть "прямоугольники" Entry и Exit вообще хз для чего они.

И ещё, в коде, который я скопировал с туториала, у меня показало ошибки в строках 45, 118 и 139. Ниже это код из туториала.

using UnityEngine;
public class BossScript : MonoBehaviour
{
    private bool hasSpawn;
    //  Component references
    private MoveScript moveScript;
    private WeaponScript[] weapons;
    private Animator animator;
    private SpriteRenderer[] renderers;
    // Boss pattern (not really an AI)
    public float minAttackCooldown = 0.5f;
    public float maxAttackCooldown = 2f;
    private float aiCooldown;
    private bool isAttacking;
    private Vector2 positionTarget;
    void Awake()
    {
        // Retrieve the weapon only once
        weapons = GetComponentsInChildren<WeaponScript>();
        // Retrieve scripts to disable when not spawned
        moveScript = GetComponent<MoveScript>();
        // Get the animator
        animator = GetComponent<Animator>();
        // Get the renderers in children
        renderers = GetComponentsInChildren<SpriteRenderer>();
    }
    void Start()
    {
        hasSpawn = false;
        // Disable everything
        // -- Collider
        collider2D.enabled = false;          /////////////////45 строка
        // -- Moving
        moveScript.enabled = false;
        // -- Shooting
        foreach (WeaponScript weapon in weapons)
        {
            weapon.enabled = false;
        }
        // Default behavior
        isAttacking = false;
        aiCooldown = maxAttackCooldown;
    }
    void Update()
    {
        // Check if the enemy has spawned
        if (hasSpawn == false)
        {
            // We check only the first renderer for simplicity.
            // But we don't know if it's the body, and eye or the mouth...
            if (renderers[0].IsVisibleFrom(Camera.main))
            {
                Spawn();
            }
        }
        else
        {
            // AI
            //------------------------------------
            // Move or attack. permute. Repeat.
            aiCooldown -= Time.deltaTime;
            if (aiCooldown <= 0f)
            {
                isAttacking = !isAttacking;
                aiCooldown = Random.Range(minAttackCooldown, maxAttackCooldown);
                positionTarget = Vector2.zero;
                // Set or unset the attack animation
                animator.SetBool("Attack", isAttacking);
            }
            // Attack
            //----------
            if (isAttacking)
            {
                // Stop any movement
                moveScript.direction = Vector2.zero;
                foreach (WeaponScript weapon in weapons)
                {
                    if (weapon != null && weapon.enabled && weapon.CanAttack)
                    {
                        weapon.Attack(true);
                        SoundEffectsHelper.Instance.MakeEnemyShotSound();
                    }
                }
            }
            // Move
            //----------
            else
            {
                // Define a target?
                if (positionTarget == Vector2.zero)
                {
                    // Get a point on the screen, convert to world
                    Vector2 randomPoint = new Vector2(Random.Range(0f, 1f), Random.Range(0f, 1f));
                    positionTarget = Camera.main.ViewportToWorldPoint(randomPoint);
                }
                // Are we at the target? If so, find a new one
                if (collider2D.OverlapPoint(positionTarget))   ////////////////////118 строка
                {
                    // Reset, will be set at the next frame
                    positionTarget = Vector2.zero;
                }
                // Go to the point
                Vector3 direction = ((Vector3)positionTarget - this.transform.position);
                // Remember to use the move script
                moveScript.direction = Vector3.Normalize(direction);
            }
        }
    }
    private void Spawn()
    {
        hasSpawn = true;
        // Enable everything
        // -- Collider
        collider2D.enabled = true;   ////////////////////////139 строка
        // -- Moving
        moveScript.enabled = true;
        // -- Shooting
        foreach (WeaponScript weapon in weapons)
        {
            weapon.enabled = true;
        }
        // Stop the main scrolling
        foreach (ScrollingScript scrolling in FindObjectsOfType<ScrollingScript>())
        {
            if (scrolling.isLinkedToCamera)
            {
                scrolling.speed = Vector2.zero;
            }
        }
    }
    void OnTriggerEnter2D(Collider2D otherCollider2D)
    {
        // Taking damage? Change animation
        ShotScript shot = otherCollider2D.gameObject.GetComponent<ShotScript>();
        if (shot != null)
        {
            if (shot.isEnemyShot == false)
            {
                // Stop attacks and start moving awya
                aiCooldown = Random.Range(minAttackCooldown, maxAttackCooldown);
                isAttacking = false;
                // Change animation
                animator.SetTrigger("Hit");
            }
        }
    }
    void OnDrawGizmos()
    {
        // A little tip: you can display debug information in your scene with Gizmos
        if (hasSpawn && isAttacking == false)
        {
            Gizmos.DrawSphere(positionTarget, 0.25f);
        }
    }
}

Но немного погуглив, я изменил код вот так. Изменения в строках 45, 118 и 139.

using UnityEngine;
public class BossScript : MonoBehaviour
{
    private bool hasSpawn;
    //  Component references
    private MoveScript moveScript;
    private WeaponScript[] weapons;
    private Animator animator;
    private SpriteRenderer[] renderers;
    // Boss pattern (not really an AI)
    public float minAttackCooldown = 0.5f;
    public float maxAttackCooldown = 2f;
    private float aiCooldown;
    private bool isAttacking;
    private Vector2 positionTarget;
    void Awake()
    {
        // Retrieve the weapon only once
        weapons = GetComponentsInChildren<WeaponScript>();
        // Retrieve scripts to disable when not spawned
        moveScript = GetComponent<MoveScript>();
        // Get the animator
        animator = GetComponent<Animator>();
        // Get the renderers in children
        renderers = GetComponentsInChildren<SpriteRenderer>();
    }
    void Start()
    {
        hasSpawn = false;
        // Disable everything
        // -- Collider
        GetComponent<Collider2D>().enabled = false;  //////////////////45 строка
        // -- Moving
        moveScript.enabled = false;
        // -- Shooting
        foreach (WeaponScript weapon in weapons)
        {
            weapon.enabled = false;
        }
        // Default behavior
        isAttacking = false;
        aiCooldown = maxAttackCooldown;
    }
    void Update()
    {
        // Check if the enemy has spawned
        if (hasSpawn == false)
        {
            // We check only the first renderer for simplicity.
            // But we don't know if it's the body, and eye or the mouth...
            if (renderers[0].IsVisibleFrom(Camera.main))
            {
                Spawn();
            }
        }
        else
        {
            // AI
            //------------------------------------
            // Move or attack. permute. Repeat.
            aiCooldown -= Time.deltaTime;
            if (aiCooldown <= 0f)
            {
                isAttacking = !isAttacking;
                aiCooldown = Random.Range(minAttackCooldown, maxAttackCooldown);
                positionTarget = Vector2.zero;
                // Set or unset the attack animation
                animator.SetBool("Attack", isAttacking);
            }
            // Attack
            //----------
            if (isAttacking)
            {
                // Stop any movement
                moveScript.direction = Vector2.zero;
                foreach (WeaponScript weapon in weapons)
                {
                    if (weapon != null && weapon.enabled && weapon.CanAttack)
                    {
                        weapon.Attack(true);
                        SoundEffectsHelper.Instance.MakeEnemyShotSound();
                    }
                }
            }
            // Move
            //----------
            else
            {
                // Define a target?
                if (positionTarget == Vector2.zero)
                {
                    // Get a point on the screen, convert to world
                    Vector2 randomPoint = new Vector2(Random.Range(0f, 1f), Random.Range(0f, 1f));
                    positionTarget = Camera.main.ViewportToWorldPoint(randomPoint);
                }
                // Are we at the target? If so, find a new one
                if (GetComponent<Collider2D>().OverlapPoint(positionTarget))  /////////////////////////118 строка
                {
                    // Reset, will be set at the next frame
                    positionTarget = Vector2.zero;
                }
                // Go to the point
                Vector3 direction = ((Vector3)positionTarget - this.transform.position);
                // Remember to use the move script
                moveScript.direction = Vector3.Normalize(direction);
            }
        }
    }
    private void Spawn()
    {
        hasSpawn = true;
        // Enable everything
        // -- Collider
        GetComponent<Collider2D>().enabled = true;   /////////////139 строка
        // -- Moving
        moveScript.enabled = true;
        // -- Shooting
        foreach (WeaponScript weapon in weapons)
        {
            weapon.enabled = true;
        }
        // Stop the main scrolling
        foreach (ScrollingScript scrolling in FindObjectsOfType<ScrollingScript>())
        {
            if (scrolling.isLinkedToCamera)
            {
                scrolling.speed = Vector2.zero;
            }
        }
    }
    void OnTriggerEnter2D(Collider2D otherCollider2D)
    {
        // Taking damage? Change animation
        ShotScript shot = otherCollider2D.gameObject.GetComponent<ShotScript>();
        if (shot != null)
        {
            if (shot.isEnemyShot == false)
            {
                // Stop attacks and start moving awya
                aiCooldown = Random.Range(minAttackCooldown, maxAttackCooldown);
                isAttacking = false;
                // Change animation
                animator.SetTrigger("Hit");
            }
        }
    }
    void OnDrawGizmos()
    {
        // A little tip: you can display debug information in your scene with Gizmos
        if (hasSpawn && isAttacking == false)
        {
            Gizmos.DrawSphere(positionTarget, 0.25f);
        }
    }
}

Помогите, пожалуйста, буду очень сильно благодарен

Answer 1

Ошибки вам выдало т.к. collider2d в старых версиях было свойством, которое делало то, что вы написали в "исправленном" варианте.

Более оптимально будет сделать так, же как в методе Awake() - создайте поле Collider2D _collider2d и в этом методе назначьте в него результат GetComponent<Collider2D>(). Т.е. "закешируйте" результат поиска компонента, как это сделано, например, с Animator

Это то, что касается вашего кода.

Что касается "прямоугольников" Entry и Exit - первый это точка из которой начинается анимирование. Т.е. базовое состояние из которого начинается движение логики анимации - в вашем случае это переход в анимацию "Idle". Состояние Exit - это состояние, в которое можно сделать "переход" из любого другого и тогда перейдя в него анимация снова начнётся из состояния Entry

Это то, что касается состояния аниматора.

Всё остальное у вас, скорее всего, правильно. Поэтому уточняйте, что именно значит "не работает". Судя по тому, что я вижу, как минимум анимация Idle должна воспроизводиться.

Если у вас не работают переходы из анимации Idle, то вы либо забыли настроить в аниматоре переменные "Hit" и "Attack", либо не настроили их использование в самих переходах

Answer 2

переходы из анимации AnyState->Hit забыли добавит(Hit) Conditions >Add to list> Hit

Answer 3

Решение вопроса оказалось настолько легким, что я даже не думал что одна галочка может "сломать" анимацию. Нужно было снять галочку из префаба Босса в Инспекторе в окне Аниматор с Apply root motion

READ ALSO
C# Отмена асинхронного метода блокирует изменение полей

C# Отмена асинхронного метода блокирует изменение полей

Использую WPF, MVVM паттернНа ряду с использованием метода Webclient

121
WPF Група одинаковых елементов с одним id

WPF Група одинаковых елементов с одним id

Например есть поле и 2 кнопки, одна добавляет, каждый раз, после нажатия в поле число, а другая кнопка- убирает

117
Visual Studio’s Emulator for Android что с ним стало?

Visual Studio’s Emulator for Android что с ним стало?

Описание эмулятора здесьНо это какая-то волшебная страница

252
Как правильно генерировать ключ RSA-2048?

Как правильно генерировать ключ RSA-2048?

Подскажите как правильно сгенерировать приватный и закрытый ключ именно для RSA-2048

110