Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Вивчайте Перехід Стану | Поведінка Ворога
Бійцівська гра в Unity

bookПерехід Стану

public class Transition
{
    Func<bool> condition;
    List<StatePourcentage> availableStates;

    public Transition(Func<bool> condition, params StatePourcentage[] statePourcentage)
    {
        this.condition = condition;
        availableStates = new List<StatePourcentage>();
        for (int i = 0; i < statePourcentage.Length; i++)
        {
            availableStates.Add(statePourcentage[i]);
        }
    }

    public State GetState()
    {
        float percentage = UnityEngine.Random.Range(0, 100);
        float currentPercentage = 0;
        foreach (var statePer in availableStates)
        {
            currentPercentage += statePer.percentage;
            if (percentage <= currentPercentage)
            {
                return statePer.state;
            }
        }
        return null;
    }

    public bool IsConditionMet()
    {
        return condition();
    }
}
public class StatePourcentage
{
    public State state;
    public float percentage;

    public StatePourcentage(State state, float percentage)
    {
        this.state = state;
        this.percentage = percentage;
    }
}

На цих зображеннях представлено класи Transition та StatePourcentage. Ці класи працюють разом для керування переходами між різними станами на основі певних умов і ймовірностей. Розглянемо, що робить цей код простими словами:

Пояснення

Клас StatePourcentage

Визначення класу: Рядок public class StatePourcentage визначає клас з назвою StatePourcentage. Цей клас зберігає інформацію про стан і відсоткову ймовірність переходу до цього стану.

Змінні-члени:

public State state; містить посилання на стан. public float percentage; містить відсоткову ймовірність переходу до цього стану.

Конструктор:

public StatePourcentage(State state, float percentage) — це конструктор. Він приймає State і float як параметри та присвоює їх змінним-членам.

Клас Transition

Визначення класу: Рядок public class Transition визначає клас з назвою Transition. Цей клас відповідає за логіку переходу між станами на основі умови та відсотків.

Змінні-члени: Func<bool> condition; — делегат, який містить функцію-умову. Ця функція повертає булеве значення, що вказує, чи виконана умова переходу.

List<StatePourcentage> availableStates; — список, який містить кілька об'єктів StatePourcentage, що представляють потенційні стани для переходу та їх відповідні ймовірності.

Конструктор: public Transition(Func<bool> condition, params StatePourcentage[] statePourcentage) — це конструктор. Він приймає функцію-умову та масив об'єктів StatePourcentage як параметри. Він ініціалізує змінну-член condition переданою функцією-умовою та створює новий список для availableStates, додаючи до нього кожен об'єкт StatePourcentage з масиву.

Метод GetState: public State GetState() — це метод, який визначає, до якого стану перейти на основі випадкового вибору та заданих відсотків. Він генерує випадкове число від 0 до 100 і перебирає доступні стани, накопичуючи їх відсотки, поки не знайде стан, що відповідає випадковому числу.

Метод IsConditionMet: public bool IsConditionMet() — це метод, який перевіряє, чи виконана умова переходу, викликаючи функцію-умову. Він повертає результат виконання цієї функції.

Як це працює для нашого ворога

Налаштування переходів: Ми визначаємо переходи між станами, вказуючи умови, за яких ці переходи відбуваються, та ймовірності переходу до кожного стану.

Визначення наступного стану: Коли спрацьовує перехід, метод GetState() випадковим чином обирає наступний стан на основі заданих ймовірностей. Це додає елемент непередбачуваності до поведінки ворога, роблячи її більш динамічною та складною.

Перевірка умов: Метод IsConditionMet() використовується для перевірки, чи виконані умови для переходу. Якщо умова істинна, перехід може відбутися, і метод GetState() визначає наступний стан.

Менеджер Станів

public class StateManager
{
    State currentState;
    Dictionary<State, List<Transition>> stateTransitions;

    public StateManager(State startingState)
    {
        currentState = startingState;
        currentState.StartState();
        stateTransitions = new Dictionary<State, List<Transition>>();
    }

    public void AddStateTransition(State state, Transition transition)
    {
        if (!stateTransitions.ContainsKey(state))
        {
            stateTransitions.Add(state, new List<Transition>());
        }
        stateTransitions[state].Add(transition);
    }

    public void ChangeState(State newState)
    {
        currentState.EndState();
        currentState = newState;
        currentState.StartState();
    }

    public void UpdateStates(float deltaTime)
    {
        currentState.UpdateState(deltaTime);
        List<Transition> stateTransitionsList = stateTransitions[currentState];
        if (stateTransitionsList == null || stateTransitionsList.Count == 0) return;
        foreach (var transition in stateTransitionsList)
        {
            if (transition.IsConditionMet())
            {
                ChangeState(transition.GetState());
                break;
            }
        }
    }
}

Зміни та доповнення

Словник переходів станів: Dictionary<State, List<Transition>> stateTransitions; — словник, що містить списки переходів для кожного стану. Кожен стан пов’язано з набором можливих переходів, які перевіряються під час оновлення стану.

Конструктор: stateTransitions = new Dictionary<State, List<Transition>>(); ініціалізує словник stateTransitions в конструкторі, забезпечуючи його готовність до зберігання переходів для різних станів.

Метод AddStateTransition: public void AddStateTransition(State state, Transition transition) додає перехід до списку переходів для вказаного стану. Якщо стан ще не має запису у словнику, створюється новий запис із порожнім списком переходів. Далі перехід додається до цього списку.

Метод UpdateStates: Метод UpdateStates оновлює поточний стан через currentState.UpdateState(deltaTime);, а потім отримує список переходів для цього стану. Кожен перехід перевіряється на виконання умови за допомогою transition.IsConditionMet(). Якщо умова виконується, викликається ChangeState(transition.GetState()); та цикл переривається, щоб запобігти кільком змінам стану за одне оновлення.

Причини внесення цих змін

Додавання словника stateTransitions та методу AddStateTransition дозволяє StateManager керувати кількома можливими переходами для кожного стану, що підвищує гнучкість і складність станового автомата. Динамічна перевірка переходів у методі UpdateStates дає змогу StateManager реагувати на різні події та умови в реальному часі. Оновлений метод гарантує, що спочатку оновлюється поточний стан, а потім перевіряються можливі переходи, що забезпечує коректне виконання логіки стану перед прийняттям рішення про перехід.

Завдяки впровадженню цих змін, StateManager стає більш здатним керувати складною та різноманітною поведінкою, що робить дії ворога більш динамічними та чутливими до ігрового середовища.

Все було зрозуміло?

Як ми можемо покращити це?

Дякуємо за ваш відгук!

Секція 3. Розділ 4

Запитати АІ

expand

Запитати АІ

ChatGPT

Запитайте про що завгодно або спробуйте одне із запропонованих запитань, щоб почати наш чат

bookПерехід Стану

public class Transition
{
    Func<bool> condition;
    List<StatePourcentage> availableStates;

    public Transition(Func<bool> condition, params StatePourcentage[] statePourcentage)
    {
        this.condition = condition;
        availableStates = new List<StatePourcentage>();
        for (int i = 0; i < statePourcentage.Length; i++)
        {
            availableStates.Add(statePourcentage[i]);
        }
    }

    public State GetState()
    {
        float percentage = UnityEngine.Random.Range(0, 100);
        float currentPercentage = 0;
        foreach (var statePer in availableStates)
        {
            currentPercentage += statePer.percentage;
            if (percentage <= currentPercentage)
            {
                return statePer.state;
            }
        }
        return null;
    }

    public bool IsConditionMet()
    {
        return condition();
    }
}
public class StatePourcentage
{
    public State state;
    public float percentage;

    public StatePourcentage(State state, float percentage)
    {
        this.state = state;
        this.percentage = percentage;
    }
}

На цих зображеннях представлено класи Transition та StatePourcentage. Ці класи працюють разом для керування переходами між різними станами на основі певних умов і ймовірностей. Розглянемо, що робить цей код простими словами:

Пояснення

Клас StatePourcentage

Визначення класу: Рядок public class StatePourcentage визначає клас з назвою StatePourcentage. Цей клас зберігає інформацію про стан і відсоткову ймовірність переходу до цього стану.

Змінні-члени:

public State state; містить посилання на стан. public float percentage; містить відсоткову ймовірність переходу до цього стану.

Конструктор:

public StatePourcentage(State state, float percentage) — це конструктор. Він приймає State і float як параметри та присвоює їх змінним-членам.

Клас Transition

Визначення класу: Рядок public class Transition визначає клас з назвою Transition. Цей клас відповідає за логіку переходу між станами на основі умови та відсотків.

Змінні-члени: Func<bool> condition; — делегат, який містить функцію-умову. Ця функція повертає булеве значення, що вказує, чи виконана умова переходу.

List<StatePourcentage> availableStates; — список, який містить кілька об'єктів StatePourcentage, що представляють потенційні стани для переходу та їх відповідні ймовірності.

Конструктор: public Transition(Func<bool> condition, params StatePourcentage[] statePourcentage) — це конструктор. Він приймає функцію-умову та масив об'єктів StatePourcentage як параметри. Він ініціалізує змінну-член condition переданою функцією-умовою та створює новий список для availableStates, додаючи до нього кожен об'єкт StatePourcentage з масиву.

Метод GetState: public State GetState() — це метод, який визначає, до якого стану перейти на основі випадкового вибору та заданих відсотків. Він генерує випадкове число від 0 до 100 і перебирає доступні стани, накопичуючи їх відсотки, поки не знайде стан, що відповідає випадковому числу.

Метод IsConditionMet: public bool IsConditionMet() — це метод, який перевіряє, чи виконана умова переходу, викликаючи функцію-умову. Він повертає результат виконання цієї функції.

Як це працює для нашого ворога

Налаштування переходів: Ми визначаємо переходи між станами, вказуючи умови, за яких ці переходи відбуваються, та ймовірності переходу до кожного стану.

Визначення наступного стану: Коли спрацьовує перехід, метод GetState() випадковим чином обирає наступний стан на основі заданих ймовірностей. Це додає елемент непередбачуваності до поведінки ворога, роблячи її більш динамічною та складною.

Перевірка умов: Метод IsConditionMet() використовується для перевірки, чи виконані умови для переходу. Якщо умова істинна, перехід може відбутися, і метод GetState() визначає наступний стан.

Менеджер Станів

public class StateManager
{
    State currentState;
    Dictionary<State, List<Transition>> stateTransitions;

    public StateManager(State startingState)
    {
        currentState = startingState;
        currentState.StartState();
        stateTransitions = new Dictionary<State, List<Transition>>();
    }

    public void AddStateTransition(State state, Transition transition)
    {
        if (!stateTransitions.ContainsKey(state))
        {
            stateTransitions.Add(state, new List<Transition>());
        }
        stateTransitions[state].Add(transition);
    }

    public void ChangeState(State newState)
    {
        currentState.EndState();
        currentState = newState;
        currentState.StartState();
    }

    public void UpdateStates(float deltaTime)
    {
        currentState.UpdateState(deltaTime);
        List<Transition> stateTransitionsList = stateTransitions[currentState];
        if (stateTransitionsList == null || stateTransitionsList.Count == 0) return;
        foreach (var transition in stateTransitionsList)
        {
            if (transition.IsConditionMet())
            {
                ChangeState(transition.GetState());
                break;
            }
        }
    }
}

Зміни та доповнення

Словник переходів станів: Dictionary<State, List<Transition>> stateTransitions; — словник, що містить списки переходів для кожного стану. Кожен стан пов’язано з набором можливих переходів, які перевіряються під час оновлення стану.

Конструктор: stateTransitions = new Dictionary<State, List<Transition>>(); ініціалізує словник stateTransitions в конструкторі, забезпечуючи його готовність до зберігання переходів для різних станів.

Метод AddStateTransition: public void AddStateTransition(State state, Transition transition) додає перехід до списку переходів для вказаного стану. Якщо стан ще не має запису у словнику, створюється новий запис із порожнім списком переходів. Далі перехід додається до цього списку.

Метод UpdateStates: Метод UpdateStates оновлює поточний стан через currentState.UpdateState(deltaTime);, а потім отримує список переходів для цього стану. Кожен перехід перевіряється на виконання умови за допомогою transition.IsConditionMet(). Якщо умова виконується, викликається ChangeState(transition.GetState()); та цикл переривається, щоб запобігти кільком змінам стану за одне оновлення.

Причини внесення цих змін

Додавання словника stateTransitions та методу AddStateTransition дозволяє StateManager керувати кількома можливими переходами для кожного стану, що підвищує гнучкість і складність станового автомата. Динамічна перевірка переходів у методі UpdateStates дає змогу StateManager реагувати на різні події та умови в реальному часі. Оновлений метод гарантує, що спочатку оновлюється поточний стан, а потім перевіряються можливі переходи, що забезпечує коректне виконання логіки стану перед прийняттям рішення про перехід.

Завдяки впровадженню цих змін, StateManager стає більш здатним керувати складною та різноманітною поведінкою, що робить дії ворога більш динамічними та чутливими до ігрового середовища.

Все було зрозуміло?

Як ми можемо покращити це?

Дякуємо за ваш відгук!

Секція 3. Розділ 4
some-alt