UPROPERTY & UFUNCTION en Unreal Engine 5 (Para Game Audio)
If you prefer to read an English version, click on this button =>
Unreal Engine Version: 5.0.2
Has pensado sobre cómo colaborar con los programadores en tu equipo sin ser un programador también? Cómo usar y extender las capacidades del código C++ con el scripting visual de Unreal Engine (Blueprints)?
La respuesta es: macros UProperty y UFunction.
Estas poderosas funciones nos permiten a nosotros, artistas y diseñadores, usar la sólida arquitectura de nuestros programadores, exponiendo sus funciones y propiedades a nuestras clases Blueprint. También, podemos empezar a considerar disparar nuestros eventos desde código C++ nosotros mismos.
En este tutorial, te mostraré las maneras más comunes y útiles de usar UProperties y UFunctions para game audio.
Vamos a crear un proyecto third-person vacio llamado “MyUE5Project” y un Sound Wave dentro de él.
También, vamos a crear una C++ Actor Class en donde vamos a crear y probar nuestras propiedades y funciones.
Necesitas tener instalado un IDE antes de continuar (Visual Studio para Windows or Xcode para Mac). Yo uso Rider como mi IDE preferido, por esta razón puede que mi interface se vea distinta a la tuya.
Documentación Oficial:
Más Recursos:
Primeros Pasos:
1. Crea tu proyecto UE5
Abre el Epic Games Launcher y crea un nuevo proyecto C++ - Third Person Project:
Tu proyecto será creado y compilado….
En tu editor UE5 ve a Tools > Open Visual Studio o Tools > Open Xcode.
Abre el Content Drawer y da click en Settings, luego seleciona Show C++ Classes.
La carpeta C++ Classes será expuesta.
En el Content Drawer ve a la carpeta "MyUE5Project”. Da click derecho y selecciona “New C++ Class”.
Crea una clase de tipo Actor y llámala “MyCPPActorClass”.
Dentro de tu IDE ve a Games/MyUEProject/Source/MyUEProject y abre los dos: “MyCPPActorClass.cpp” y "MyCPPActorClass.h”.
Sobre los archivos .h y .cpp: Cada vez que creamos una clase en Unreal Engine, este crea dos archivos. El archivo con extensión .h o “header/encabezado” va a contener las “Declaraciones” (Propiedades/Variables, Constantes y Funciones), y el archivo con extensión .cpp va a contener las “Implementaciones” o "Definiciones” de estas declaraciones.
2. USoundWave Property
Dentro de"MyUE5ProjectCharacter.h” crea una propiedad de clase “USoundWave” y llámala “testSound”.
USoundWave* testSound;
Guarda tu código modificado. Vuelve al proyecto UE y compila.
Arrastra "MyCPPActorClass” dentro del outliner de tu mapa.
Antes de continuar, da click derecho para crear una clase tipo Blueprint basada en “MyCPPActorClass” llamada “MyBPActorClass”. Arrástrala dentro del outliner del mapa, también.
UPROPERTY:
Vamos a usar “testSound” para cada ejemplo, entonces debes guardar y compilar los cambios en cada caso para probarlos. Adicionalmente, vamos a añadir Category=”Audio” como un “specifier” para que sea más fácil encontrarlo dentro de los editores. Puedes usar cualquier nombre que gustes para la categoría.
1. Visible Anywhere | Edit Anywhere
Visible Anywhere: Visible en el editor principal y en el editor blueprint | No editable | Expuesto a las Clases Padres y a Objetos (Instancias).
.h file:
UPROPERTY(VisibleAnywhere, Category="Audio") USoundWave* testSound;
Edit Anywhere: Visible en el editor principal y en el editor blueprint | Editable | Expuesto a las Clases Padres y a Objetos (Instancias).
.h file:
UPROPERTY(EditAnywhere, Category="Audio") USoundWave* testSound;
Click en las imágenes para expandir:
2. Visible Defaults Only | Edit Defaults Only
Visible Defaults Only: Visible en el editor principal y en el editor blueprint | No editable | Expuesto a las Clases Padres exclusivamente.
.h file:
UPROPERTY(VisibleDefaultsOnly, Category="Audio") USoundWave* testSound;
Edit Defaults Only: Visible en el editor principal y en el editor blueprint | Editable | Expuesto a las Clases Padres exclusivamente.
.h file:
UPROPERTY(EditDefaultsOnly, Category="Audio") USoundWave* testSound;
Click en las imágenes para expandir:
3. Visible Instance Only | Edit Instance Only
Visible Instance Only: Visible en el editor principal y en el editor blueprint | No editable | Expuesto a Objetos (Instancias), exclusivamente.
.h file:
UPROPERTY(VisibleInstanceOnly, Category="Audio") USoundWave* testSound;
Edit Instance Only: Visible en el editor principal y en el editor blueprint | Editable | Expuesto a Objetos (Instancias), exclusivamente.
.h file:
UPROPERTY(EditInstanceOnly, Category="Audio") USoundWave* testSound;
Click en las imágenes para expandir:
7. Blueprint Read Only
Expuesto a clases Blueprint | No editable | Obtener propiedad: Sí - Establecer propiedad: No
UPROPERTY(BlueprintReadOnly, Category="Audio") USoundWave* testSound;
Click en las imágenes para expandir:
8. Blueprint Read Write
Expuesto a clases Blueprint | Editable | Obtener propiedad: Sí - Establecer propiedad: Sí
UPROPERTY(BlueprintReadWrite, Category="Audio") USoundWave* testSound;
Click en las imágenes para expandir:
Es posible combinar Visible/Edit con Blueprint read, y Category como especificadores del macro UPROPERTY.
Ejemplo:
UPROPERTY(VisibleDefaultsOnly, BlueprintReadWrite, Category="My Category") USoundWave* testSound;
UFUNCTION:
Ahora, vamos a crear una función llamada "PlayTestSound()” que va a disparar una propiedad USoundWave y en algunos casos va a retornar este texto: “PlayTestSound() function triggered”. Vamos a usar la misma función y modificarla para cada ejemplo, entonces debes guardar y compilar los cambios en cada caso para probarlos. Adicionalmente, vamos a añadir Category=”Audio” como un “specifier” para que sea más fácil encontrarlo dentro de los editores. Puedes usar cualquier nombre que gustes para la categoría.
Información importante sobre esta función:
UGameplayStatics::PlaySound2D(this, testSound);
this: El USoundWave será colocado al objeto en donde este script está conectado. to the Object where this script is attached.
testSound: El USoundWave el cual esta función va a reproducir.
1. Blueprint Callable
Puede ser insertado en un graph blueprint después de un un Event function | Puede ser void(vacío), aceptar y retornar una propiedad también. Es posible tener una función tipo void y una tipo property input combinada, y una función tipo return y una property input, también.
Ejemplo #1 (Void):
.h file:
UFUNCTION(BlueprintCallable, Category="Audio") void PlayTestSound();
.cpp file:
void AMyCPPActorClass::PlayTestSound() { UGameplayStatics::PlaySound2D(this, testSound); }
Ejemplo #2 (Property Input):
.h file:
UFUNCTION(BlueprintCallable, Category="Audio") void PlayTestSound(USoundWave* soundWave);
.cpp file:
void AMyCPPActorClass::PlayTestSound(USoundWave* soundWave) { UGameplayStatics::PlaySound2D(this, soundWave); }
Ejemplo #3 (Return Property):
.h file:
UFUNCTION(BlueprintCallable, Category="Audio") FString PlayTestSound();
.cpp file:
FString AMyCPPActorClass::PlayTestSound() { UGameplayStatics::PlaySound2D(this, testSound); return "PlayTestSound() function triggered"; }
2. Blueprint Pure
Puede ser insertado en un graph blueprint sin un pin de ejecución | Debe retornar una propiedad. Puede aceptar una propiedad, también.
Ejemplo #1 (Return Property):
.h file:
UFUNCTION(BlueprintPure, Category="Audio") FString PlayTestSound();
.cpp file:
FString AMyCPPActorClass::PlayTestSound() { UGameplayStatics::PlaySound2D(this, testSound); return "PlayTestSound() function triggered"; }
Ejemplo #2 (Return Property + Property Input):
.h file:
UFUNCTION(BlueprintPure, Category="Audio") FString PlayTestSound(USoundWave* soundWave);
.cpp file:
FString AMyCPPActorClass::PlayTestSound(USoundWave* soundWave) { UGameplayStatics::PlaySound2D(this, soundWave); return "PlayTestSound() function triggered"; }
3. Blueprint Implementable Event
Puede ser insertado y debe ser ser implementado en un graph blueprint, entonces no necesita ser implementato en el archivo .cpp | Puede ser void(vacío), aceptar y retornar una propiedad también. Es posible tener una función tipo void y una tipo property input combinada, y una función tipo return y una property input, también.
Ejemplo #1 (Void):
.h file:
UFUNCTION(BlueprintImplementableEvent, Category="Audio") void PlayTestSound();
Ejemplo #2 (Property Input):
.h file:
UFUNCTION(BlueprintImplementableEvent, Category="Audio") void PlayTestSound(USoundWave* soundWave);
Ejemplo #3 (Return Property):
Para añadir este tipo de evento al graph blueprint, debes ir a Functions>Override>Play Test Sound. Esto va a abrir otro graph en donde vas a crear tu implementación.
.h file:
UFUNCTION(BlueprintImplementableEvent, Category="Audio") FString PlayTestSound();
Ejemplo #4 (Return Property + Property Input):
Para añadir este tipo de evento al graph blueprint, debes ir a Functions>Override>Play Test Sound. Esto va a abrir otro graph en donde vas a crear tu implementación.
.h file:
UFUNCTION(BlueprintImplementableEvent, Category="Audio") FString PlayTestSound(USoundWave* soundWave);
4. Blueprint Native Event
Puede ser insertado en un graph blueprint sin un pin de ejecución. Este evento puede ser implementado en C++ y extendido en Blueprints, o anulada por completo | Puede ser insertado y debe ser ser implementado en un graph blueprint, entonces no necesita ser implementato en el archivo .cpp | Puede ser void(vacío), aceptar y retornar una propiedad también. Es posible tener una función tipo void y una tipo property input combinada, y una función tipo return y una property input, también.
Es importante crear una definición especial en el archivo .cpp la cual va a contener la funcionalidad deseada. Puedes traer esta implementación a tu graph blueprint haciendo doble click al nodo de tu función y seleccionando “Add call to parent function”, ahora puedes extender esta función en Blueprints, o dejarla vacía y desechar la implementación C++ nativa.
Ejemplo:
void [MyClass]::[MyFunction]_Implementation() { //My function's body }
Ejemplo #1 (Void):
.h
UFUNCTION(BlueprintNativeEvent, Category="Audio") void PlayTestSound();
.cpp
void AMyCPPActorClass::PlayTestSound_Implementation() { UGameplayStatics::PlaySound2D(this, testSound); }
Ejemplo #2 (Property Input):
.h
UFUNCTION(BlueprintNativeEvent, Category="Audio") void PlayTestSound(USoundWave* soundWave);
.cpp
void AMyCPPActorClass::PlayTestSound_Implementation(USoundWave* soundWave) { UGameplayStatics::PlaySound2D(this, soundWave); }
Ejemplo #3 (Return Property):
Para añadir este tipo de evento al graph blueprint, debes ir a Functions>Override>Play Test Sound. Esto va a abrir otro graph en donde vas a crear tu implementación.
.h
UFUNCTION(BlueprintNativeEvent, Category="Audio") FString PlayTestSound();
.cpp
FString AMyCPPActorClass::PlayTestSound_Implementation() { UGameplayStatics::PlaySound2D(this, testSound); return "PlayTestSound() function triggered"; }
5. Prueba tus funciones
En el editor, da click en el Content Drawer y luego da click en Import para añadir un archivo de audio .Wav. Como alternativa, puedes arrastrar tu archivo directamente en el editor.
IMPORTANTE: Por el momento UE5 solo soporta archivos de 16 bits. Si prefieres, puedes usar este archivo de audio:
Para hacer una prueba simple, vamos a llamar a nuestra función “PlayTestSound()” dentro de “BeginPlay()”, o insertar un nodo en nuestro graph Blueprint después de Begin Play Event. Guarda, compila, ve al editor principal y da click en el botón Play. Deberías poder escuchar tu sonido ahora!
Blueprint:
C++:
void AMyCPPActorClass::BeginPlay() { Super::BeginPlay(); PlayTestSound(); }