Transición 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;
}
}
En estas imágenes, observamos una clase Transition
y una clase StatePourcentage
. Estas clases trabajan en conjunto para gestionar las transiciones entre diferentes estados basándose en ciertas condiciones y probabilidades. A continuación, se explica de manera sencilla qué realiza este código:
Explicación
Clase StatePourcentage
Definición de la clase:
La línea public class StatePourcentage
define una clase llamada StatePourcentage
. Esta clase almacena información sobre un estado y el porcentaje de probabilidad de transición a ese estado.
Variables miembro:
public State state;
almacena una referencia a un estado.
public float percentage;
almacena el porcentaje de probabilidad de transición a este estado.
Constructor:
public StatePourcentage(State state, float percentage)
es un método constructor. Recibe un State
y un float
como parámetros y los asigna a las variables miembro.
Clase Transition
Definición de la clase:
La línea public class Transition
define una clase llamada Transition
. Esta clase gestiona la lógica para la transición entre estados basada en una condición y porcentajes.
Variables miembro:
Func<bool> condition;
es un delegado que almacena una función de condición. Esta función retorna un valor booleano que indica si se cumple la condición de transición.
List<StatePourcentage> availableStates;
es una lista que almacena múltiples objetos StatePourcentage
, representando los posibles estados a los que se puede transicionar y sus respectivas probabilidades.
Constructor:
public Transition(Func<bool> condition, params StatePourcentage[] statePourcentage)
es un método constructor. Recibe una función de condición y un arreglo de objetos StatePourcentage
como parámetros. Inicializa la variable miembro condition
con la función de condición proporcionada y crea una nueva lista para availableStates
, agregando cada objeto StatePourcentage
del arreglo a esta lista.
Método GetState:
public State GetState()
es un método que determina a qué estado se debe transicionar basado en una selección aleatoria y los porcentajes definidos. Genera un número aleatorio entre 0 y 100 e itera a través de los estados disponibles, acumulando sus porcentajes hasta encontrar el estado que corresponde con el número aleatorio.
Método IsConditionMet:
public bool IsConditionMet()
es un método que verifica si se cumple la condición de transición llamando a la función de condición. Retorna el resultado de la función de condición.
Funcionamiento para Nuestro Enemigo
Configuración de transiciones: Se definen transiciones entre estados, especificando las condiciones bajo las cuales ocurren estas transiciones y las probabilidades de transición a cada estado.
Determinación del siguiente estado: Cuando se activa una transición, el método GetState()
selecciona aleatoriamente el siguiente estado según las probabilidades definidas. Esto añade un elemento de imprevisibilidad al comportamiento del enemigo, haciéndolo más dinámico y desafiante.
Verificación de condiciones: El método IsConditionMet()
se utiliza para comprobar si se cumplen las condiciones para una transición. Si la condición es verdadera, la transición puede ocurrir y el método GetState()
determina el siguiente estado.
Gestor 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())
{
ChangeState(transition.GetState());
break;
}
}
}
}
Cambios y Adiciones
Diccionario de Transiciones de Estado: Dictionary<State, List<Transition>> stateTransitions;
es un diccionario que almacena listas de transiciones para cada estado. Cada estado está asociado con una lista de posibles transiciones que pueden ser verificadas al actualizar el estado.
Constructor: stateTransitions = new Dictionary<State, List<Transition>>();
inicializa el diccionario stateTransitions
en el constructor, asegurando que esté listo para almacenar transiciones para diferentes estados.
Método AddStateTransition: public void AddStateTransition(State state, Transition transition)
es un método que añade una transición a la lista de transiciones para un estado dado. Si el estado aún no tiene una entrada en el diccionario, se crea una nueva entrada con una lista vacía de transiciones. Luego, la transición se añade a la lista de transiciones para el estado especificado.
Método UpdateStates: El método UpdateStates
ha sido actualizado para primero verificar las transiciones obteniendo la lista de transiciones para el estado actual después de actualizarlo con currentState.UpdateState(deltaTime);
. Luego evalúa cada transición en la lista para comprobar si se cumple la condición de transición usando transition.IsConditionMet()
. Si se cumple una condición de transición, cambia el estado usando ChangeState(transition.GetState());
y rompe el ciclo para evitar múltiples cambios de estado en una sola actualización.
Razón de Estos Cambios
La adición del diccionario stateTransitions
y el método AddStateTransition
permite que el StateManager
gestione múltiples transiciones potenciales para cada estado, aumentando la flexibilidad y complejidad de la máquina de estados. Al verificar dinámicamente las transiciones dentro del método UpdateStates
, el StateManager
permite que el enemigo responda a diferentes eventos y condiciones en tiempo real. El método actualizado asegura que el estado actual se actualice primero, seguido de la comprobación de posibles transiciones, lo que garantiza la correcta ejecución de la lógica del estado antes de tomar decisiones de transición.
Al implementar estos cambios, el StateManager
se vuelve más capaz de manejar comportamientos complejos y variados, haciendo que las acciones del enemigo sean más dinámicas y receptivas al entorno del juego.
¡Gracias por tus comentarios!
Pregunte a AI
Pregunte a AI
Pregunte lo que quiera o pruebe una de las preguntas sugeridas para comenzar nuestra charla
Awesome!
Completion rate improved to 3.33
Transición de Estado
Desliza para mostrar el menú
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;
}
}
En estas imágenes, observamos una clase Transition
y una clase StatePourcentage
. Estas clases trabajan en conjunto para gestionar las transiciones entre diferentes estados basándose en ciertas condiciones y probabilidades. A continuación, se explica de manera sencilla qué realiza este código:
Explicación
Clase StatePourcentage
Definición de la clase:
La línea public class StatePourcentage
define una clase llamada StatePourcentage
. Esta clase almacena información sobre un estado y el porcentaje de probabilidad de transición a ese estado.
Variables miembro:
public State state;
almacena una referencia a un estado.
public float percentage;
almacena el porcentaje de probabilidad de transición a este estado.
Constructor:
public StatePourcentage(State state, float percentage)
es un método constructor. Recibe un State
y un float
como parámetros y los asigna a las variables miembro.
Clase Transition
Definición de la clase:
La línea public class Transition
define una clase llamada Transition
. Esta clase gestiona la lógica para la transición entre estados basada en una condición y porcentajes.
Variables miembro:
Func<bool> condition;
es un delegado que almacena una función de condición. Esta función retorna un valor booleano que indica si se cumple la condición de transición.
List<StatePourcentage> availableStates;
es una lista que almacena múltiples objetos StatePourcentage
, representando los posibles estados a los que se puede transicionar y sus respectivas probabilidades.
Constructor:
public Transition(Func<bool> condition, params StatePourcentage[] statePourcentage)
es un método constructor. Recibe una función de condición y un arreglo de objetos StatePourcentage
como parámetros. Inicializa la variable miembro condition
con la función de condición proporcionada y crea una nueva lista para availableStates
, agregando cada objeto StatePourcentage
del arreglo a esta lista.
Método GetState:
public State GetState()
es un método que determina a qué estado se debe transicionar basado en una selección aleatoria y los porcentajes definidos. Genera un número aleatorio entre 0 y 100 e itera a través de los estados disponibles, acumulando sus porcentajes hasta encontrar el estado que corresponde con el número aleatorio.
Método IsConditionMet:
public bool IsConditionMet()
es un método que verifica si se cumple la condición de transición llamando a la función de condición. Retorna el resultado de la función de condición.
Funcionamiento para Nuestro Enemigo
Configuración de transiciones: Se definen transiciones entre estados, especificando las condiciones bajo las cuales ocurren estas transiciones y las probabilidades de transición a cada estado.
Determinación del siguiente estado: Cuando se activa una transición, el método GetState()
selecciona aleatoriamente el siguiente estado según las probabilidades definidas. Esto añade un elemento de imprevisibilidad al comportamiento del enemigo, haciéndolo más dinámico y desafiante.
Verificación de condiciones: El método IsConditionMet()
se utiliza para comprobar si se cumplen las condiciones para una transición. Si la condición es verdadera, la transición puede ocurrir y el método GetState()
determina el siguiente estado.
Gestor 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())
{
ChangeState(transition.GetState());
break;
}
}
}
}
Cambios y Adiciones
Diccionario de Transiciones de Estado: Dictionary<State, List<Transition>> stateTransitions;
es un diccionario que almacena listas de transiciones para cada estado. Cada estado está asociado con una lista de posibles transiciones que pueden ser verificadas al actualizar el estado.
Constructor: stateTransitions = new Dictionary<State, List<Transition>>();
inicializa el diccionario stateTransitions
en el constructor, asegurando que esté listo para almacenar transiciones para diferentes estados.
Método AddStateTransition: public void AddStateTransition(State state, Transition transition)
es un método que añade una transición a la lista de transiciones para un estado dado. Si el estado aún no tiene una entrada en el diccionario, se crea una nueva entrada con una lista vacía de transiciones. Luego, la transición se añade a la lista de transiciones para el estado especificado.
Método UpdateStates: El método UpdateStates
ha sido actualizado para primero verificar las transiciones obteniendo la lista de transiciones para el estado actual después de actualizarlo con currentState.UpdateState(deltaTime);
. Luego evalúa cada transición en la lista para comprobar si se cumple la condición de transición usando transition.IsConditionMet()
. Si se cumple una condición de transición, cambia el estado usando ChangeState(transition.GetState());
y rompe el ciclo para evitar múltiples cambios de estado en una sola actualización.
Razón de Estos Cambios
La adición del diccionario stateTransitions
y el método AddStateTransition
permite que el StateManager
gestione múltiples transiciones potenciales para cada estado, aumentando la flexibilidad y complejidad de la máquina de estados. Al verificar dinámicamente las transiciones dentro del método UpdateStates
, el StateManager
permite que el enemigo responda a diferentes eventos y condiciones en tiempo real. El método actualizado asegura que el estado actual se actualice primero, seguido de la comprobación de posibles transiciones, lo que garantiza la correcta ejecución de la lógica del estado antes de tomar decisiones de transición.
Al implementar estos cambios, el StateManager
se vuelve más capaz de manejar comportamientos complejos y variados, haciendo que las acciones del enemigo sean más dinámicas y receptivas al entorno del juego.
¡Gracias por tus comentarios!