Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Aprenda Transição de Estado | Comportamento do Inimigo
Jogo de Luta no Unity

book
Transição de Estado

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;
}
}

Nestas imagens, vemos uma classe Transition e uma classe StatePourcentage. Essas classes trabalham juntas para lidar com transições entre diferentes estados com base em certas condições e probabilidades. Vamos explicar o que esse código faz em termos simples:

Explicação

Classe StatePourcentage

Definição da Classe: A linha public class StatePourcentage define uma classe chamada StatePourcentage. Esta classe mantém informações sobre um estado e a chance percentual de transição para esse estado.

Variáveis Membro:

public State state; mantém uma referência a um estado. public float percentage; mantém a chance percentual de transição para este estado.

Construtor:

public StatePourcentage(State state, float percentage) é um método construtor. Ele recebe um State e um float como parâmetros e os atribui às variáveis membro.

Classe Transition

Definição da Classe: A linha public class Transition define uma classe chamada Transition. Esta classe lida com a lógica de transição entre estados com base em uma condição e percentuais.

Variáveis Membro: Func<bool> condition; é um delegado que mantém uma função de condição. Esta função retorna um booleano indicando se a condição de transição foi atendida.

List<StatePourcentage> availableStates; é uma lista que mantém múltiplos objetos StatePourcentage, representando estados potenciais para transição e suas respectivas probabilidades.

Construtor: public Transition(Func<bool> condition, params StatePourcentage[] statePourcentage) é um método construtor. Ele recebe uma função de condição e um array de objetos StatePourcentage como parâmetros. Ele inicializa a variável membro condition com a função de condição fornecida e cria uma nova lista para availableStates, adicionando cada objeto StatePourcentage do array a esta lista.

Método GetState: public State GetState() é um método que determina para qual estado transitar com base em uma seleção aleatória e nos percentuais fornecidos. Ele gera um número aleatório entre 0 e 100 e itera pelos estados disponíveis, acumulando seus percentuais até encontrar o estado que corresponde ao número aleatório.

Método IsConditionMet: public bool IsConditionMet() é um método que verifica se a condição de transição foi atendida chamando a função de condição. Ele retorna o resultado da função de condição.

Como Funciona para Nosso Inimigo

Configuração de Transição: Definimos transições entre estados, especificando as condições sob as quais essas transições ocorrem e as probabilidades de transição para cada estado.

Determinando o Próximo Estado: Quando uma transição é acionada, o método GetState() seleciona aleatoriamente o próximo estado com base nas probabilidades definidas. Isso adiciona um elemento de imprevisibilidade ao comportamento do inimigo, tornando-o mais dinâmico e desafiador.

Verificando Condições: O método IsConditionMet() é usado para verificar se as condições para uma transição foram atendidas. Se a condição for verdadeira, a transição pode ocorrer, e o método GetState() determina o próximo estado.

Gerenciador de Estados

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())

Alterações e Adições

Dicionário de Transições de Estado: Dictionary<State, List<Transition>> stateTransitions; é um dicionário que mantém listas de transições para cada estado. Cada estado está associado a uma lista de possíveis transições que podem ser verificadas ao atualizar o estado.

Construtor: stateTransitions = new Dictionary<State, List<Transition>>(); inicializa o dicionário stateTransitions no construtor, garantindo que esteja pronto para armazenar transições para diferentes estados.

Método AddStateTransition: public void AddStateTransition(State state, Transition transition) é um método que adiciona uma transição à lista de transições para um determinado estado. Se o estado ainda não tiver uma entrada no dicionário, uma nova entrada é criada com uma lista vazia de transições. A transição é então adicionada à lista de transições para o estado especificado.

Método UpdateStates: O método UpdateStates foi atualizado para primeiro verificar as transições recuperando a lista de transições para o estado atual após atualizá-lo com currentState.UpdateState(deltaTime);. Em seguida, avalia cada transição na lista para verificar se a condição de transição é atendida usando transition.IsConditionMet(). Se uma condição de transição for atendida, ele muda o estado usando ChangeState(transition.GetState()); e interrompe o loop para evitar múltiplas mudanças de estado em uma única atualização.

Por Que Essas Alterações Foram Feitas

A adição do dicionário stateTransitions e do método AddStateTransition permite que o StateManager gerencie múltiplas transições potenciais para cada estado, aumentando a flexibilidade e complexidade da máquina de estados. Ao verificar dinamicamente as transições dentro do método UpdateStates, o StateManager permite que o inimigo responda a diferentes eventos e condições em tempo real. O método atualizado garante que o estado atual seja atualizado primeiro, seguido pela verificação de possíveis transições, o que assegura a execução adequada da lógica de estado antes de tomar decisões de transição.

Ao implementar essas mudanças, o StateManager se torna mais capaz de lidar com comportamentos complexos e variados, tornando as ações do inimigo mais dinâmicas e responsivas ao ambiente do jogo.

Tudo estava claro?

Como podemos melhorá-lo?

Obrigado pelo seu feedback!

Seção 3. Capítulo 4
some-alt