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
- Delegados y Eventos
- Expresiones Lambda
- LINQ (Language Integrated Query)
- Genéricos
- Programación Asíncrona con
asyncyawait
- 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.
- 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.
- 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.
- 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.
- Programación Asíncrona con
async y await
async y awaitLa 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
- Introducción a Unity e Instalación
- Descripción General de la Interfaz de Unity
- Creando Tu Primer Proyecto
- Objetos de Juego Básicos y Componentes
Módulo 2: Programación Básica en Unity
- Introducción a C# para Unity
- Creación y Adjunto de Scripts
- Entendiendo MonoBehaviour
- Manejo Básico de Entradas
Módulo 3: Trabajando con Activos
- Importación y Gestión de Activos
- Uso de la Tienda de Activos
- Creación y Uso de Prefabs
- Animación Básica
Módulo 4: Física y Colisiones
- Introducción a la Física en Unity
- Cuerpos Rígidos y Colisionadores
- Detección Básica de Colisiones
- Uso de Materiales Físicos
Módulo 5: Interfaz de Usuario (UI)
- Introducción a la UI de Unity
- Creación y Personalización de Elementos UI
- Manejo de Eventos UI
- Creación de Menús y HUDs
Módulo 6: Audio en Unity
- Introducción al Audio en Unity
- Importación y Uso de Clips de Audio
- Programación Básica de Audio
- Audio 3D y Sonido Espacial
Módulo 7: Programación Avanzada
- Conceptos Avanzados de C# para Unity
- Corutinas y Programación Asíncrona
- Objetos Scriptables
- Editores Personalizados y Gizmos
Módulo 8: Física Avanzada e IA
- Técnicas Avanzadas de Física
- Búsqueda de Caminos y Navegación
- Programación Básica de IA
- Máquinas de Estado y Árboles de Comportamiento
Módulo 9: Optimización y Rendimiento
- Técnicas de Perfilado y Optimización
- Gestión de Memoria
- Reducción de Llamadas de Dibujo
- Optimización de Física y Colisiones
