← Назад к вопросам

Можно ли дописать логику к аниматору?

1.2 Junior🔥 101 комментариев
#C# и ООП#Другое

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Можно ли дописать логику к аниматору в Unity?

Да, конечно! Аниматор в Unity — это не просто проигрыватель анимаций, а мощный конечный автомат (State Machine), управление которым можно и нужно расширять с помощью скриптов. Сама по себе система Animator Controller визуальна и ограничена, но через код вы получаете полный контроль над переходами, параметрами, состояниями и даже самими анимациями.

Основные способы дописать логику к аниматору

1. Управление параметрами аниматора из скриптов

Это самый распространенный способ. Вы получаете доступ к компоненту Animator и меняете его параметры (Float, Int, Bool, Trigger), что вызывает запланированные в контроллере переходы.

using UnityEngine;

public class PlayerMovement : MonoBehaviour
{
    private Animator animator;
    private float moveSpeed = 5f;

    void Start()
    {
        animator = GetComponent<Animator>();
    }

    void Update()
    {
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");

        // Вычисляем скорость для параметра аниматора
        float speed = new Vector3(horizontal, 0, vertical).magnitude;
        animator.SetFloat("Speed", speed);

        // Управляем прыжком через триггер
        if (Input.GetButtonDown("Jump") && IsGrounded())
        {
            animator.SetTrigger("Jump");
        }

        // Управляем состоянием атаки через bool
        if (Input.GetButtonDown("Fire1"))
        {
            animator.SetBool("IsAttacking", true);
        }
    }

    // Этот метод можно вызвать из события анимации Attack
    public void OnAttackAnimationEnd()
    {
        animator.SetBool("IsAttacking", false);
    }
}

2. Использование событий анимации (Animation Events)

Позволяют вызывать методы скрипта в конкретные моменты времени на клипе анимации. Незаменимы для синхронизации геймплейных действий (нанесение урона, звук шага, создание эффекта).

public class AttackController : MonoBehaviour
{
    public void DealDamage() // Вызывается из события анимации
    {
        // Логика расчета и нанесения урона
        Debug.Log("Damage dealt at frame: " + Time.frameCount);
    }

    public void PlayStepSound()
    {
        AudioManager.Instance.PlayFootstep();
    }
}

3. Расширенные техники через подклассы StateMachineBehaviour

Это самый мощный инструмент для добавления логики непосредственно к состояниям аниматора. Вы можете прикрепить скрипт к любому состоянию в контроллере.

using UnityEngine;

public class CustomAttackState : StateMachineBehaviour
{
    // Вызывается при входе в состояние
    override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        // Например, активировать оружие
        animator.GetComponent<Player>().EquipWeapon(true);
    }

    // Вызывается на каждом Update, пока активно состояние
    override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        // Можно проверять ввод или другие условия
        if (Input.GetButtonUp("Fire1"))
        {
            animator.SetBool("ComboReady", true);
        }
    }

    // Вызывается при выходе из состояния
    override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        // Гарантированно деактивировать оружие, даже если состояние было прервано
        animator.GetComponent<Player>().EquipWeapon(false);
        animator.SetBool("ComboReady", false);
    }
}

4. Прямое управление слоями и IK (Inverse Kinematics)

Через код можно управлять весами слоев, масками, включать/выключать IK для процедурной анимации (например, чтобы персонаж смотрел на объект или ставил ноги на неровную поверхность).

void Update()
{
    // Плавное переключение веса слоя с анимацией верхней части тела
    float aimWeight = isAiming ? 1f : 0f;
    animator.SetLayerWeight(1, Mathf.Lerp(animator.GetLayerWeight(1), aimWeight, Time.deltaTime * 10));
}

// Callback для настройки IK
void OnAnimatorIK(int layerIndex)
{
    if (isAiming && lookTarget != null)
    {
        animator.SetLookAtWeight(1f, 0.5f, 0.8f);
        animator.SetLookAtPosition(lookTarget.position);
    }
}

Ключевые принципы и лучшие практики

  • Разделение ответственности: Аниматор должен управлять визуальным состоянием (какая анимация проигрывается), а игровая логика (можно ли атаковать, жив ли персонаж) должна оставаться в основных скриптах.
  • Абстракция через параметры: Внешний код взаимодействует с аниматором только через набор параметров. Это делает систему модульной и удобной для отладки.
  • Использование триггеров: Триггеры (SetTrigger) идеальны для одноразовых действий (прыжок, удар), которые должны быть обработаны аниматором ровно один раз.
  • Оптимизация: Кэшируйте ссылку на Animator в Start() или Awake(), избегайте вызова GetComponent каждый кадр. Используйте хэшированные имена параметров (Animator.StringToHash("ParamName")) для повышения производительности в часто вызываемых методах.

Вывод: Система аниматора Unity спроектирована с расчетом на расширение кодом. Комбинация визуального редактирования Animator Controller и программирования через C# скрипты дает разработчику гибкий и эффективный инструмент для создания сложного и отзывчивого анимационного поведения любой сложности.