En este módulo, profundizaremos en conceptos avanzados de C# que son esenciales para desarrollar juegos complejos y eficientes en Unity. Estos conceptos te permitirán escribir código más robusto, reutilizable y mantenible.

Índice del Tema

  1. Delegados y Eventos
  2. Expresiones Lambda
  3. LINQ (Language Integrated Query)
  4. Genéricos
  5. Programación Asíncrona con async y await

  1. Delegados y Eventos

Delegados

Un delegado es un tipo que representa referencias a métodos con una lista de parámetros y un tipo de retorno específico. Los delegados son útiles para definir métodos de callback y eventos.

Ejemplo de Delegado

public delegate void MyDelegate(string message);

public class DelegateExample
{
    public MyDelegate myDelegate;

    public void Start()
    {
        myDelegate = PrintMessage;
        myDelegate("Hello, Delegates!");
    }

    void PrintMessage(string message)
    {
        Debug.Log(message);
    }
}

En este ejemplo, MyDelegate es un delegado que apunta al método PrintMessage.

Eventos

Los eventos son una forma de que una clase notifique a otras clases cuando algo interesante sucede. Los eventos se basan en delegados.

Ejemplo de Evento

public class EventExample
{
    public delegate void MyEventHandler(string message);
    public event MyEventHandler OnMessageReceived;

    public void TriggerEvent()
    {
        if (OnMessageReceived != null)
        {
            OnMessageReceived("Event Triggered!");
        }
    }
}

public class EventListener
{
    private EventExample eventExample;

    public void Start()
    {
        eventExample = new EventExample();
        eventExample.OnMessageReceived += HandleEvent;
        eventExample.TriggerEvent();
    }

    void HandleEvent(string message)
    {
        Debug.Log(message);
    }
}

En este ejemplo, OnMessageReceived es un evento que se dispara en el método TriggerEvent.

  1. Expresiones Lambda

Las expresiones lambda son una forma concisa de escribir métodos anónimos. Son útiles para escribir código más limpio y legible.

Ejemplo de Expresión Lambda

public class LambdaExample
{
    public delegate int Operation(int x, int y);

    public void Start()
    {
        Operation add = (x, y) => x + y;
        int result = add(3, 4);
        Debug.Log(result); // Output: 7
    }
}

En este ejemplo, (x, y) => x + y es una expresión lambda que suma dos números.

  1. LINQ (Language Integrated Query)

LINQ es una poderosa característica de C# que permite realizar consultas sobre colecciones de datos de manera declarativa.

Ejemplo de LINQ

using System.Linq;

public class LINQExample
{
    public void Start()
    {
        int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        var evenNumbers = numbers.Where(n => n % 2 == 0);

        foreach (var num in evenNumbers)
        {
            Debug.Log(num); // Output: 2, 4, 6, 8, 10
        }
    }
}

En este ejemplo, numbers.Where(n => n % 2 == 0) utiliza LINQ para filtrar números pares.

  1. Genéricos

Los genéricos permiten definir clases, métodos y delegados con un tipo de dato que se especifica en tiempo de compilación, proporcionando mayor flexibilidad y seguridad de tipos.

Ejemplo de Genéricos

public class GenericExample<T>
{
    private T item;

    public void SetItem(T newItem)
    {
        item = newItem;
    }

    public T GetItem()
    {
        return item;
    }
}

public class TestGeneric
{
    public void Start()
    {
        GenericExample<int> intExample = new GenericExample<int>();
        intExample.SetItem(5);
        Debug.Log(intExample.GetItem()); // Output: 5

        GenericExample<string> stringExample = new GenericExample<string>();
        stringExample.SetItem("Hello");
        Debug.Log(stringExample.GetItem()); // Output: Hello
    }
}

En este ejemplo, GenericExample<T> es una clase genérica que puede manejar cualquier tipo de dato.

  1. Programación Asíncrona con async y await

La programación asíncrona permite ejecutar tareas en segundo plano sin bloquear el hilo principal, mejorando la eficiencia y la capacidad de respuesta de la aplicación.

Ejemplo de async y await

using System.Threading.Tasks;

public class AsyncExample
{
    public async void Start()
    {
        Debug.Log("Before Delay");
        await Task.Delay(2000);
        Debug.Log("After Delay");
    }
}

En este ejemplo, Task.Delay(2000) simula una operación asíncrona que se completa después de 2 segundos.

Ejercicios Prácticos

Ejercicio 1: Delegados y Eventos

Crea un delegado y un evento que notifique cuando un jugador recoge un objeto en el juego. Implementa una clase Player y una clase Item para simular esta interacción.

Ejercicio 2: Expresiones Lambda y LINQ

Utiliza expresiones lambda y LINQ para filtrar una lista de objetos Enemy que tienen menos de 50 puntos de vida. Imprime los nombres de estos enemigos.

Ejercicio 3: Genéricos

Crea una clase genérica Inventory<T> que pueda almacenar diferentes tipos de objetos del juego (por ejemplo, armas, pociones). Implementa métodos para agregar y obtener objetos del inventario.

Ejercicio 4: Programación Asíncrona

Implementa una función asíncrona que simule la carga de datos de un servidor. Utiliza async y await para esperar la carga y luego imprime un mensaje en la consola.

Soluciones

Solución Ejercicio 1

public delegate void ItemCollectedHandler(string itemName);

public class Player
{
    public event ItemCollectedHandler OnItemCollected;

    public void CollectItem(string itemName)
    {
        Debug.Log("Item Collected: " + itemName);
        OnItemCollected?.Invoke(itemName);
    }
}

public class Item
{
    private Player player;

    public Item(Player player)
    {
        this.player = player;
        player.OnItemCollected += HandleItemCollected;
    }

    void HandleItemCollected(string itemName)
    {
        Debug.Log("Player collected: " + itemName);
    }
}

Solución Ejercicio 2

using System.Collections.Generic;
using System.Linq;

public class Enemy
{
    public string Name { get; set; }
    public int Health { get; set; }
}

public class Game
{
    public void Start()
    {
        List<Enemy> enemies = new List<Enemy>
        {
            new Enemy { Name = "Goblin", Health = 30 },
            new Enemy { Name = "Orc", Health = 70 },
            new Enemy { Name = "Troll", Health = 40 }
        };

        var weakEnemies = enemies.Where(e => e.Health < 50);

        foreach (var enemy in weakEnemies)
        {
            Debug.Log(enemy.Name);
        }
    }
}

Solución Ejercicio 3

using System.Collections.Generic;

public class Inventory<T>
{
    private List<T> items = new List<T>();

    public void AddItem(T item)
    {
        items.Add(item);
    }

    public T GetItem(int index)
    {
        return items[index];
    }
}

public class Game
{
    public void Start()
    {
        Inventory<string> weaponInventory = new Inventory<string>();
        weaponInventory.AddItem("Sword");
        Debug.Log(weaponInventory.GetItem(0)); // Output: Sword

        Inventory<int> potionInventory = new Inventory<int>();
        potionInventory.AddItem(5);
        Debug.Log(potionInventory.GetItem(0)); // Output: 5
    }
}

Solución Ejercicio 4

using System.Threading.Tasks;

public class DataLoader
{
    public async Task LoadData()
    {
        Debug.Log("Loading data...");
        await Task.Delay(3000); // Simulate data loading
        Debug.Log("Data loaded.");
    }
}

public class Game
{
    public async void Start()
    {
        DataLoader dataLoader = new DataLoader();
        await dataLoader.LoadData();
    }
}

Conclusión

En este módulo, hemos explorado conceptos avanzados de C# que son cruciales para el desarrollo de juegos en Unity. Desde delegados y eventos hasta programación asíncrona, estos conceptos te permitirán escribir código más eficiente y manejable. Asegúrate de practicar estos conceptos con los ejercicios proporcionados para consolidar tu comprensión. En el próximo módulo, profundizaremos en técnicas avanzadas de física y programación de inteligencia artificial en Unity.

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