En este módulo, exploraremos dos técnicas avanzadas de programación de inteligencia artificial (IA) en Unity: las máquinas de estado y los árboles de comportamiento. Estas técnicas son fundamentales para crear comportamientos complejos y realistas en los personajes de los juegos.

Máquinas de Estado

¿Qué es una Máquina de Estado?

Una máquina de estado es un modelo de comportamiento que permite a un objeto cambiar entre diferentes estados en respuesta a eventos o condiciones. Cada estado define un comportamiento específico y las transiciones entre estados están controladas por condiciones lógicas.

Componentes de una Máquina de Estado

  1. Estados: Representan diferentes comportamientos o modos de operación.
  2. Transiciones: Condiciones que permiten el cambio de un estado a otro.
  3. Eventos: Acciones o condiciones que desencadenan transiciones.

Implementación de una Máquina de Estado en Unity

Paso 1: Definir los Estados

Primero, definimos los estados como una enumeración:

public enum State
{
    Idle,
    Patrol,
    Chase,
    Attack
}

Paso 2: Crear la Clase de la Máquina de Estado

Creamos una clase que maneje los estados y las transiciones:

public class StateMachine : MonoBehaviour
{
    public State currentState;

    void Start()
    {
        currentState = State.Idle;
    }

    void Update()
    {
        switch (currentState)
        {
            case State.Idle:
                HandleIdleState();
                break;
            case State.Patrol:
                HandlePatrolState();
                break;
            case State.Chase:
                HandleChaseState();
                break;
            case State.Attack:
                HandleAttackState();
                break;
        }
    }

    void HandleIdleState()
    {
        // Lógica para el estado Idle
        if (/* condición para cambiar a Patrol */)
        {
            currentState = State.Patrol;
        }
    }

    void HandlePatrolState()
    {
        // Lógica para el estado Patrol
        if (/* condición para cambiar a Chase */)
        {
            currentState = State.Chase;
        }
    }

    void HandleChaseState()
    {
        // Lógica para el estado Chase
        if (/* condición para cambiar a Attack */)
        {
            currentState = State.Attack;
        }
    }

    void HandleAttackState()
    {
        // Lógica para el estado Attack
        if (/* condición para cambiar a Idle */)
        {
            currentState = State.Idle;
        }
    }
}

Ejercicio Práctico

Ejercicio: Implementa una máquina de estado para un enemigo que patrulla entre puntos y persigue al jugador cuando está cerca.

Solución:

public class EnemyAI : MonoBehaviour
{
    public Transform[] patrolPoints;
    public Transform player;
    public float chaseDistance = 5f;
    private int currentPatrolIndex;
    private State currentState;

    void Start()
    {
        currentState = State.Patrol;
        currentPatrolIndex = 0;
    }

    void Update()
    {
        switch (currentState)
        {
            case State.Patrol:
                Patrol();
                break;
            case State.Chase:
                Chase();
                break;
        }
    }

    void Patrol()
    {
        Transform targetPoint = patrolPoints[currentPatrolIndex];
        transform.position = Vector3.MoveTowards(transform.position, targetPoint.position, Time.deltaTime);

        if (Vector3.Distance(transform.position, targetPoint.position) < 0.1f)
        {
            currentPatrolIndex = (currentPatrolIndex + 1) % patrolPoints.Length;
        }

        if (Vector3.Distance(transform.position, player.position) < chaseDistance)
        {
            currentState = State.Chase;
        }
    }

    void Chase()
    {
        transform.position = Vector3.MoveTowards(transform.position, player.position, Time.deltaTime);

        if (Vector3.Distance(transform.position, player.position) > chaseDistance)
        {
            currentState = State.Patrol;
        }
    }
}

Árboles de Comportamiento

¿Qué es un Árbol de Comportamiento?

Un árbol de comportamiento es una estructura jerárquica que organiza comportamientos en nodos. Cada nodo puede ser una acción, una condición o una combinación de ambas. Los árboles de comportamiento son más flexibles y escalables que las máquinas de estado.

Componentes de un Árbol de Comportamiento

  1. Nodos de Acción: Realizan tareas específicas.
  2. Nodos de Control: Dirigen el flujo de ejecución (secuencias, selectores).
  3. Nodos de Condición: Evalúan condiciones y deciden el flujo.

Implementación de un Árbol de Comportamiento en Unity

Paso 1: Definir los Nodos

Creamos una clase base para los nodos:

public abstract class Node
{
    public abstract bool Execute();
}

Paso 2: Crear Nodos de Acción y Condición

public class ActionNode : Node
{
    private System.Action action;

    public ActionNode(System.Action action)
    {
        this.action = action;
    }

    public override bool Execute()
    {
        action();
        return true;
    }
}

public class ConditionNode : Node
{
    private System.Func<bool> condition;

    public ConditionNode(System.Func<bool> condition)
    {
        this.condition = condition;
    }

    public override bool Execute()
    {
        return condition();
    }
}

Paso 3: Crear Nodos de Control

public class SequenceNode : Node
{
    private List<Node> children;

    public SequenceNode(List<Node> children)
    {
        this.children = children;
    }

    public override bool Execute()
    {
        foreach (var child in children)
        {
            if (!child.Execute())
            {
                return false;
            }
        }
        return true;
    }
}

public class SelectorNode : Node
{
    private List<Node> children;

    public SelectorNode(List<Node> children)
    {
        this.children = children;
    }

    public override bool Execute()
    {
        foreach (var child in children)
        {
            if (child.Execute())
            {
                return true;
            }
        }
        return false;
    }
}

Ejercicio Práctico

Ejercicio: Implementa un árbol de comportamiento para un enemigo que patrulla y ataca al jugador si está cerca.

Solución:

public class EnemyAI : MonoBehaviour
{
    private Node rootNode;

    void Start()
    {
        rootNode = new SelectorNode(new List<Node>
        {
            new SequenceNode(new List<Node>
            {
                new ConditionNode(() => Vector3.Distance(transform.position, player.position) < chaseDistance),
                new ActionNode(() => Chase())
            }),
            new ActionNode(() => Patrol())
        });
    }

    void Update()
    {
        rootNode.Execute();
    }

    void Patrol()
    {
        // Lógica de patrullaje
    }

    void Chase()
    {
        // Lógica de persecución
    }
}

Conclusión

En esta sección, hemos aprendido sobre las máquinas de estado y los árboles de comportamiento, dos técnicas avanzadas para la programación de IA en Unity. Las máquinas de estado son útiles para comportamientos simples y bien definidos, mientras que los árboles de comportamiento ofrecen mayor flexibilidad y escalabilidad para comportamientos complejos. Con estos conocimientos, puedes crear personajes de juego más inteligentes y realistas.

En el próximo módulo, exploraremos técnicas avanzadas de física y cómo aplicarlas en Unity para mejorar la interacción y realismo en tus juegos.

Curso de Unity

Módulo 1: Introducción a Unity

Módulo 2: Programación Básica en Unity

Módulo 3: Trabajando con Activos

Módulo 4: Física y Colisiones

Módulo 5: Interfaz de Usuario (UI)

Módulo 6: Audio en Unity

Módulo 7: Programación Avanzada

Módulo 8: Física Avanzada e IA

Módulo 9: Optimización y Rendimiento

Módulo 10: Publicación y Más Allá

© Copyright 2024. Todos los derechos reservados