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

Как реализовать конечный автомат (FSM) для ИИ в Unity?

1.0 Junior🔥 121 комментариев
#Unity Core

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

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

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

Реализация конечного автомата (FSM) для ИИ в Unity

Конечный автомат (Finite State Machine, FSM) — это фундаментальный архитектурный паттерн для управления поведением ИИ, который я успешно использую в проектах уже много лет. В Unity существует несколько подходов к реализации FSM, от простых до сложных, в зависимости от требований проекта.

Базовая архитектура FSM

В основе FSM лежит концепция состояний (states), переходов (transitions) и управляющего класса (state machine controller). Каждое состояние инкапсулирует конкретное поведение NPC.

public interface IState
{
    void Enter();
    void Execute();
    void Exit();
}

Классическая реализация на C#

Наиболее распространенный подход — создание базового класса StateMachine и производных состояний.

public class EnemyStateMachine : MonoBehaviour
{
    private IState currentState;
    private Dictionary<System.Type, IState> stateDictionary;
    
    private void Start()
    {
        // Инициализация состояний
        stateDictionary = new Dictionary<System.Type, IState>
        {
            { typeof(IdleState), new IdleState(this) },
            { typeof(ChaseState), new ChaseState(this) },
            { typeof(AttackState), new AttackState(this) },
            { typeof(PatrolState), new PatrolState(this) }
        };
        
        ChangeState(typeof(IdleState));
    }
    
    private void Update()
    {
        currentState?.Execute();
    }
    
    public void ChangeState(System.Type newStateType)
    {
        if (!stateDictionary.ContainsKey(newStateType)) return;
        
        currentState?.Exit();
        currentState = stateDictionary[newStateType];
        currentState.Enter();
    }
}

Пример конкретного состояния

public class ChaseState : IState
{
    private EnemyStateMachine machine;
    private Transform player;
    private float chaseSpeed = 3.5f;
    private float stoppingDistance = 2f;
    
    public ChaseState(EnemyStateMachine machine)
    {
        this.machine = machine;
        player = GameObject.FindGameObjectWithTag("Player").transform;
    }
    
    public void Enter()
    {
        Debug.Log("Начинаю преследование игрока");
        // Включение визуальных индикаторов
        machine.GetComponent<Renderer>().material.color = Color.red;
    }
    
    public void Execute()
    {
        if (player == null) return;
        
        Vector3 direction = player.position - machine.transform.position;
        float distance = direction.magnitude;
        
        // Проверка условий перехода
        if (distance > 20f)
        {
            machine.ChangeState(typeof(PatrolState));
            return;
        }
        
        if (distance <= stoppingDistance)
        {
            machine.ChangeState(typeof(AttackState));
            return;
        }
        
        // Движение к игроку
        machine.transform.position += direction.normalized * chaseSpeed * Time.deltaTime;
        machine.transform.LookAt(player.position);
    }
    
    public void Exit()
    {
        Debug.Log("Заканчиваю преследование");
    }
}

Ключевые аспекты реализации

Дизайн переходов между состояниями:

  • Жесткие переходы — прямое указание следующего состояния в коде
  • Условные переходы — система условий (Condition-based transitions)
  • Таблицы переходов — внешние данные для настройки поведения

Управление данными состояний:

  • Использование ScriptableObject для хранения параметров состояний
  • Создание StateData контейнеров для настройки баланса
  • Система черного досье (Blackboard) для общей памяти ИИ

Оптимизация и лучшие практики:

  • Использование enum вместо строк для идентификации состояний
  • Кэширование ссылок на компоненты в методе Enter()
  • Реализация состояния по умолчанию для обработки ошибок
  • Добавление состояния паузы для управления временной остановкой ИИ

Расширенные техники

Для сложных проектов я рекомендую:

  1. Иерархические FSM (HFSM) — состояния могут содержать под-состояния
  2. Система стека состояний — для приоритетных прерываний (например, получение урона)
  3. Визуальные редакторы — создание собственного EditorWindow для дизайна поведения
  4. Интеграция с анимацией — через Animator Controller parameters или собственный Animation State Machine

Интеграция с Unity

// Пример системы условий для переходов
[System.Serializable]
public class TransitionCondition
{
    public string parameterName;
    public ConditionType conditionType;
    public float thresholdValue;
    
    public bool CheckCondition(EnemyAI ai)
    {
        float value = ai.GetParameter(parameterName);
        
        switch(conditionType)
        {
            case ConditionType.LessThan: return value < thresholdValue;
            case ConditionType.GreaterThan: return value > thresholdValue;
            default: return false;
        }
    }
}

Преимущества и ограничения

Преимущества:

  • Четкая структура и организация кода
  • Легкость отладки и модификации
  • Предсказуемость поведения ИИ
  • Хорошая производительность для среднего количества состояний

Ограничения:

  • Сложность масштабирования при большом количестве состояний
  • Возможность возникновения "взрыва состояний"
  • Не подходит для сложных поведенческих деревьев

Для большинства игровых ИИ (враги, NPC, боссы) классический FSM остается оптимальным выбором благодаря своей простоте, предсказуемости и производительности. Для более сложных поведенческих систем стоит рассмотреть Behavior Trees или Utility AI, но FSM всегда будет надежным фундаментом в арсенале Unity-разработчика.