Jorge Vallejo Blog

Blog del creativo, ilustrador y profesor de videojuegos Jorge Vallejo

Unreal Engine 5 sistema de daño (Damage system) introducción

Unreal Engine tiene un sistema de daño integrado que permite aplicar y recibir daño en videojuegos tanto multijugador como locales. Este sistema se basa en eventos que se ejecutan en el servidor y que se comunican con cada cliente para afectar a los actores del juego, como los personajes, enemigos, players, vehículos etc
Cuando creamos un proyecto que no es multijugador el servidor y el cliente son el mismo por lo que el sistema de daño funciona tanto multijugador como solo.
Con la idea de facilitar la tarea de dañar todos los actores en Unreal Engine tienen definido un boolean llamado Can be damaged que determina si el actor puede ser dañado o no.
Esta implementación esta en la clase base Actor , así que todos los que heredan de ella poseen esta propiedad*.


Hacer y recibir daño
Usarlo es muy sencillo solo requiere de dos agentes, uno va a ser el que cause el daño y otro es el que lo recibe.
Por ejemplo vamos a crear una zona de fuego.
Podemos crear un collision que detecte quien entra en la zona para después aplicarle daño.
El evento del servidor Apply Damage es una función estática que se puede llamar desde cualquier blueprint

Por otro lado implementaremos que sucede cuando se recibe el daño, por ejemplo en el Player Character llamamos al evento AnyDamage el cual se dispara cuando recibe un daño, el player character tiene marcado Can be damage en true por el constructor del Character


Recibiendo daño

Con Event AnyDamage se declara que va a pasar cuando se reciba el daño, cualquier daño, en este caso va a ser el de la caja, podremos realizar mas comprobaciones para controlar quien generó el daño.

El resultado es que si el jugador entra en el área del daño llama a la función Apply Damage del servidor y todos los que tengan Event AnyDamage reciben daño

No confundir daño con live span
Live span esta pensado para crear una cuenta atrás, un tiempo de vida de un objeto, tras el cual se destruye solo, es independiente del daño.

Resumen:

Se necesita un elemento que haga daño Apply Damage, otro que lo reciba AnyDamage y la capacidad de recibir daño activada, Can be damaged true.


*Sobre la herencia del daño

La modernización de la programación hace que hoy día sea mas correcto tener un componente separado para evaluar el daño o implementar un interface que directamente hacer que TODOS los actores sean susceptibles de ser dañados, cuando muchos de ellos jamás usaran esa propiedad, sin embargo gana en facilidad y rapidez al tener ya el sistema implementado.

Introducción a las Enumeraciones en Programación: Una Guía para Principiantes

Las enumeraciones son la solución para mejorar la legibilidad y facilidad de uso de tu código.
En esta guía completa, aprenderás todo lo que necesitas saber sobre las enumeraciones, desde su definición hasta su uso en diferentes lenguajes de programación.

¿Qué son las enumeraciones?

En programación, una enumeración (también llamada “enum”) es un tipo de dato que define un conjunto de valores relacionados. Es una forma útil de organizar y agrupar valores que tienen un significado similar.
Las enumeraciones se usan para ayudarnos como humanos a entender el código ya que consiguen que sea menos abstracto, fácil de entender, claro y evita confusiones.

Ejemplo sin usar enumeraciones Mapa del tesoro:
Imagina que tienes que definir puntos cardinales para después ser comparados y saber en que dirección está un objeto respecto al mapa del tesoro, si está en el :Norte, Noroeste, Noreste, Este, Sureste, Sur, Suroeste y Oeste

Puedes usar un entero direccion para guardar ese valor, pero.. ¿Cuánto vale?
Como vas a necesitar comparar el valor decides escribirlo en un comentario

// Norte = 0 // Noreste = 1 // Este = 2 // Sureste = 3 // Sur = 4 // Suroeste = 5 // Oeste = 6 // Noroeste = 7
int direccion = 1;

Así puedes comparar la dirección y saber donde esta ubicado el objeto

if (direccion == 0) {
  std::cout << "Esta en el norte." << std::endl;
} else if (direccion == 1) {
  std::cout << "Esta en el noreste." << std::endl;
} else if (direccion == 2) {
  std::cout << "Esta en el este." << std::endl;
} else if (direccion == 3) {
  std::cout << "Esta en el sureste." << std::endl;
} else if (direccion == 4) {
  std::cout << "Esta en  el sur." << std::endl;
} else if (direccion == 5) {
  std::cout << "Esta en el suroeste." << std::endl;
} else if (direccion == 6) {
  std::cout << "Esta en el oeste." << std::endl;
} else if (direccion == 7) {
  std::cout << "Esta en el noroeste." << std::endl;
} else {
  std::cout << "Dirección no válida." << std::endl;
}

Problemas con este enfoque:

  • Falta de legibilidad: El código es difícil de entender, ya que los valores numéricos no tienen un significado claro.
  • Mantenimiento deficiente: Es difícil agregar nuevos puntos cardinales o modificar los existentes.
  • Errores: Es fácil cometer errores al usar valores numéricos incorrectos.

Cuando escribimos código debemos tener presente que al menos dos personas lo van a leer : tu yo actual, y tu yo futuro cuando repases el código.
Imagina que ves un objeto que tiene la variable direccionEnterrado=4 y han pasado un par de semanas desde que escribiste el código
– 4 ¿Qué era? ¿Era sur o era suroeste?
– ¿Dónde tengo apuntado lo que corresponde cada valor?
Ahí es donde entra la gracia de la enumeración, aclarar, evitar errores y ser más fácil de leer.

Ventajas de usar una enumeración:

  • Mayor legibilidad: El código es más fácil de entender, ya que se usan nombres descriptivos para los valores.
  • Mantenimiento mejorado: Es más fácil agregar nuevos puntos cardinales o modificar los existentes.
  • Seguridad de tipos: Las enumeraciones evitan errores al usar valores no válidos.

Ejemplo usando enumeraciones Mapa del tesoro:

Usar enumeraciones requiere de un paso previo, definir la propia enumeracion como va a identificar direcciones podemos llamarla puntosCardinales

En diferentes lenguajes de programación
C++ (Unreal Engine):

enum class PuntosCardinales : uint8 {
  Norte = 0,
  Noreste = 1,
  Este = 2,
  Sureste = 3,
  Sur = 4,
  Suroeste = 5,
  Oeste = 6,
  Noroeste = 7
};
from enum import Enum

class PuntosCardinales(Enum):
  Norte = 0
  Noreste = 1
  Este = 2
  Sureste = 3
  Sur = 4
  Suroeste = 5
  Oeste = 6
  Noroeste = 7
public enum PuntosCardinales {
  Norte = 0,
  Noreste = 1,
  Este = 2,
  Sureste = 3,
  Sur = 4,
  Suroeste = 5,
  Oeste = 6,
  Noroeste = 7
}
const PuntosCardinales = {
  NORTE: 0,
  NORESTE: 1,
  ESTE: 2,
  SURESTE: 3,
  SUR: 4,
  SUROESTE: 5,
  OESTE: 6,
  NOROESTE: 7
};

Una vez definida la enumeración en lugar de guardar un numero guardamos una opción de la misma.

PuntosCardinales direccion = PuntosCardinales::Noreste;

Ahora si cualquiera que vea el código sabe que se ha guardado Noreste , es mucho más fácil de entender, tanto para tu yo de ahora como para el futuro como para un compañero que use tu código.

Las enumeraciones casan muy bien con los switch ya que se evalúan casos así:


switch (direccion) {
  case PuntosCardinales::Norte:
    UE_LOG(LogTemp, Warning, TEXT("Tesoro ubicado en Norte"));
    break;
  case PuntosCardinales::Noreste:
    UE_LOG(LogTemp, Warning, TEXT("Tesoro ubicado en Noreste"));
    break;
  case PuntosCardinales::Este:
    UE_LOG(LogTemp, Warning, TEXT("Tesoro ubicado en Este"));
    break;
  case PuntosCardinales::Sureste:
    UE_LOG(LogTemp, Warning, TEXT("Tesoro ubicado en Sureste"));
    break;
  case PuntosCardinales::Sur:
    UE_LOG(LogTemp, Warning, TEXT("Tesoro ubicado en Sur"));
    break;
  case PuntosCardinales::Suroeste:
    UE_LOG(LogTemp, Warning, TEXT("Tesoro ubicado en Suroeste"));
    break;
  case PuntosCardinales::Oeste:
    UE_LOG(LogTemp, Warning, TEXT("Tesoro ubicado en Oeste"));
    break;
  case PuntosCardinales::Noroeste:
    UE_LOG(LogTemp, Warning, TEXT("Tesoro ubicado en Noroeste"));
    break;
}

Las enumeraciones ofrecen varias ventajas:

  • Mejora la legibilidad del código: Al usar nombres descriptivos para los valores, el código se vuelve más fácil de entender y mantener.
  • Seguridad de tipos: Las enumeraciones evitan errores al asegurarnos de que solo se usen los valores válidos.
  • Facilidad de uso: Las enumeraciones simplifican el código al evitar la necesidad de usar constantes numéricas.

Conclusión

Las enumeraciones son una herramienta esencial para escribir código limpio, eficiente y fácil de entender. Con esta guía, estás listo para comenzar a usar enumeraciones en tus propios programas.

Si te ha gustado este articulo compártelo y si tienes algo mas que añadir no dudes en dejar un comentario.

Genera visual studio proyect files en windows 11

Es posible que te haya ocurrido que necesitas generar los archivos .sln para abrir un proyecto de Unreal Engine con un IDE como Visual Studio pero de repente ves que no aparece esa opción, tranquilo si que esta.

Pasos:

  1. Botón derecho sobre el archivo de uproject

2) Ve a Mostrar más opciones

Y te aparecerá Generate Visual Studio project files

Vaya susto.

Quiz de Cine

4
Created by Jorge Vallejo

Cine

Cine Quiz

1 / 9

¿Cuál es el título de la novela en la que se basa la película "El resplandor" (1980)?

2 / 9

¿En qué serie de televisión la actriz Elisabeth Moss interpreta a una mujer que escapa de una secta religiosa?

3 / 9

¿En qué hotel se desarrolla la historia de "El resplandor" (1980)?

4 / 9

¿Qué actor interpreta a Tony Stark en Iron Man (2008)?

5 / 9

¿Cuál es el nombre del actor que interpreta a Jon Snow en la serie "Juego de Tronos"?

6 / 9

¿Cuál es el título de la película de Pixar que se centra en un personaje llamado Miguel Rivera?

7 / 9

¿Qué actriz interpreta a Carol Danvers en la película "Capitana Marvel" (2019)?

8 / 9

¿Cuál es el nombre del personaje principal en la serie "Breaking Bad"?

9 / 9

¿En qué serie de televisión el personaje Eleven tiene habilidades psicoquinéticas?

Your score is

The average score is 100%

0%

Proyecto: Recuperación de huerta, del mundo real a Unreal 5

¿Puede el mundo digital ser útil en el mundo físico? ¿Y si llevamos la huerta al mundo del videojuego?

La tecnología detrás de Unreal nos permite recrear la realidad hasta el extremo de hacerla prácticamente indistinguible de una fotografía, por eso Unreal ya se usa en estudios de arquitectura que deben presentar Renders de como quedará el proyecto, para ir mas allá de un simple plano, las recreaciones digitales son cada vez más realistas y la distancia entre el concepto digital y su realización real es cada vez menor.

Recreación en Unreal https://www.cosasdearquitectos.com/

Aun que mi especialidad es el mundo del videojuego, tengo el conocimiento suficiente para poder hacer una aproximación del mundo real al digital, lo suficientemente buena, para que me sirva a la hora de tomar decisiones.

Recreando el invernadero en 3D
Lo primero que hice fue tomar medidas de cada uno de los arcos del invernadero, después los recree usando Blender simplemente cree un arco y utilizando la herramienta Array generé los demás.

Para la cobertura de plástico utilice un plano, al cual di propiedades de simulación de tela usando Cloth, y a los arcos les di detección de colisiones con Collision

Después simule la física , para obtener el resultado del plano envolviendo los arcos

En algunos puntos el plástico se metía por dentro de los arcos, tras hacer la simulación remodele utilizando las herramientas de esculpido de Blender, principalmente la de inflado y la de suavizado.

Finalmente me lo lleve a Unreal5 a un nivel vacío y ajuste los materiales. Para el suelo de momento estoy usando un plano, pero le meteré un landscape para que sea más fácil la colocación de las plantas y recrear otras partes de la huerta.

Invernadero 3D en Unreal 5

Se ve bastante vacío, pero va cogiendo forma, lo que me interesa de este proyecto es conjugar la realidad con lo digital, por lo que iré incorporando elementos reales como el camino que va al invernadero, marcado de lindes etc,

Cesta de pan, en Unreal Engine

Homenaje al cuadro del mismo nombre de Salvador Dali, creado con el motor de videojuegos Unreal Engine 5, los modelos 3D son de Quixel, me resulto muy curioso pensar en como Dali había realizado la composición, en su cuadro el pan esta dado la vuelta , a mi sin embargo me interesaba más mostrar la miga con sus agujeros

La magia de la composición esta en el fondo negro que hace que toda nuestra atención se centre en la cesta, es muy difícil recrear la iluminación exacta del cuadro puesto q la luz esta pintada y reinterpretada, al final opte por colocar las luces lo más parecido posible, colocando una luz trasera que aisla parte de la mesa, sin mas sentido que el artístico.

Detalle del cuadro “Cesta de pan” de Salvador Dali

Creando una bombilla en Unreal 5, encendido y apagado en c++

Unreal 5 y el sistema de iluminación en tiempo real Lumen, nos permiten tener materiales con emisión que no solo van a crear un halo suavizado , sino que realmente iluminan.

Para ello tendremos que crear un material con Emission, el que mejor resultado me ha dado es Surface, y convertirlo en parámetro quedando:

Ahora viene algo que al principio parece extraño pero que luego tiene toda su lógica, y es crear dinámicamente una copia del material , modificarlo y reasignarlo.

Es necesario crear una copia ya que si se pudiera, creo que Unreal no deja manipular el material directamente, estaríamos modificando las propiedades del material en todos los objetos que lo tuvieran, por lo que un cambio en el emissor cambiaria todos y normalmente lo que se busca es tener control sobre cada uno

  1. Obtener copia dinámica del material, para ello tenemos que fijarnos en que índice está, lo ideal es crear una variable para poder cambiarlo
 DynMaterial = UMaterialInstanceDynamic::Create(LampMesh->GetMaterial(indexOfMaterial), this);

Donde DynMaterial es UMaterialInstanceDynamic* DynMaterial;

2. Modificar los parámetros, aquí es muy importante que el nombre del parámetro y el que vamos a pasar coincidan, de nuevo crear una variable ParamEmissionName (FName ParamEmissionName = FName(TEXT(“EmissionIntesity”));) para el nombre

DynMaterial->SetScalarParameterValue(ParamEmissionName, 0.0f);

3. Por último reasignar la copia del material al elemento, sino se habrá creado la copia pero no tendrá dueño, LampMesh es mesh del objeto que contiene los materiales definido como UStaticMeshComponent* LampMesh;

 LampMesh->SetMaterial(indexOfMaterial, DynMaterial);

Crear un videojuego para móvil V con Unity: Construir nivel

YouTube player

Continuamos con la recreación de Duet para móviles Duet con Unity y C# En este vídeo trabajaremos:

-Creando un constructor para el nivel

– Instanciando GameObjects

– Uso de bucles para posicionar

– Uso de aleatorios

– Mejorando el constructor con un sistema codificado

Codificar la información es crear un código para relacionar datos, así podemos utilizar matrices bidimensionales para crear las piezas