Buscar en el blog

miércoles, 14 de abril de 2021

¿Cómo importar una clase blueprint a una clase C++ en Unreal Engine? ¿Cómo funciona un GameMode blueprint desde C++?

  ¿Es posible acceder a las definiciones hechas en Blueprint desde C++ en Unreal Engine?



Para que no pierdas tiempo leyendo todo el post desde ya voy a contestarte que NO ES POSIBLE  importar una clase blueprint a una clase C++ en Unreal Engine, sin embargo vamos a analizar el problema y buscar las posibles soluciones.

Imaginemos que estamos haciendo un flappy bird y necesitamos manejar el puntaje o saber cuando esta muerto el jugador. Para eso recurrimos a clases con variables globales. En otros motores como Godot Engine y unity3D se suelen usar clases de tipo "singleton", osea es una clase con una sola instancía que posee variables y métodos para ser llamadas desde diferentes objetos. Una característica de este tipo de clases es verificar que no exista una duplicada y si existe, destruirla.



Esto en Unreal Engine tiene un nombre tecnico llamado  GAMEMODE y puede ser creado tanto en C++ como en Blueprint, sin embargo el problema surge cuando queremos referenciar esos GAMEMODE creados como blueprint desde una clase C++,( Por ejemplo al pasar por un area sumar el puntaje). Sino sabes lo que es un GameMode en este tutorial de Unreal Engine Latam nos explican que es un GameMode.




Por defecto Unreal Engine trae un GamoModeBase, sin embargo podemos crear uno nuevo tanto en C++ como en blueprint de forma personalizada y agregarlo en las opciones del mundo.



Entonces, sino no podés acceder a las definiciones hechas en Blueprint desde C++ , cómo las importamos desde C++. 

¿cómo podes solucionar este problema?



 En general la solución es en el otro sentido, definís clases base en C++ con UFUNCTION(BlueprintImplementableEvent) y las implementás en las clases derivadas de BP, o las definís con BlueprintNativeEvent si querés tener algo general en C++ y cosas propias del BP en la implementación del BP.
Por ejemplo, si el BP tiene un MeshComponent al que querés acceder desde C++ pero la clase base de C++ no lo tiene, podés hacer algo como:
UFUNCTION(BlueprintImplementableEvent)
UMeshComponent* GetMeshComponent() const;
y en BP implementás GetMeshComponent para que devuelve la referencia al componente. Después en C++ podés llamar a GetMeshComponent para acceder al MeshComponent del BP.
Desde C++ podés obtener una referencia a un BP con el path (no con un include, se usa una función pero no me acuerdo el nombre), pero no podés acceder a nada de lo que tiene definido el BP.
Otra opción si no querés hacer una clase base es hacer una interfaz en C++ y que el BP la implemente, después desde código una vez que obtenés una referencia al objeto podés usar los métodos de la interfaz para acceder a los componentes.


Sin embargo se puede referenciar al GameMode blueprint desde C++ usando esto:





El problema pasa cuando queres hacer el casting, ya que podés hacer referencia al GameMode, pero no hacer el casting a la clase blurprint GameMode personalizada... Osea en Blurprint sería asi: haces referencia al GameMode, luego casting al GamemodePersonalizado y luego podes acceder a todas las variables, métodos, etc



Eso muy común. En C++ la variable reglasJuego es de tipo AGameModeBase aunque la hayas definido como TSubclassOf, así que solo podés usar métodos y funciones de AGameModeBase. Como los tipos de Blueprint no son visibles desde C++ en tiempo de compilación, no podés ni castear la variable a BP_ReglasJuego, ni acceder a las funciones y propiedades internas que hayas definido sólo en BP. A mi siempre me sirvió tener una clase base propia en C++ derivada de AGameMode y ahí le puedo agregar todo lo que necesite que sea visible en C++. Después hacés que BP_ReglasJuego herede de esa clase propia, y en la variable ponés TSubclassOf<AClaseGameModeTuyaDeC++>...
Siempre es complicado pasar cosas que tenés solo en BP a C++. En proyectos en los que trabajé nos pasaba todo el tiempo, siempre quedan cosas que no podés pasar por completo a C++ por la cantidad de dependencias en BP y tenés que rebuscartela con BlueprintImplementableEvents y cosas de ese estilo.


¿Entonces en proyectos que se usa C++ siempre esconveniente usar el GameMode directo en una clase C++?.. 
El tema es cuando tenés que referenciar puntajes,cosas de UI, si está muerto, vivo, etc..
Y obviamente siempre hay blueprint de por medio.



Es preferible poner todo lo que puedas en C++, primero porque siempre programas con código y además porque en equipos grandes los Blueprint son incómodos (no se puede hacer merge con GIT).
En algunos proyectos siempre hay clases propias derivadas de las clases de Unreal (ej, MiGameMode, MiGameState, MiPlayerController, MiPlayerState. etc), e incluso jerarquías de eso (CaptureTheFlagGameMode, CaptureTheFlagGameState, FreeForAllGameMode, FreeForAllGameState). Todo lo que necesitamos en C++ lo definimos en esas clases, y si por alguna razón es muy complicado usamos BlueprintImplementableEvent.



¿ y cómo hacemos con los elementos de interface, casi siempre hay que hacer referencias?


Para UI también siempre usamos una clase en C++ derivada de UUserWidget (o incluso de una clase propia tipo MiUserWidget), y los widgets en BP derivan de esas clases específicas (ej: UMainMenuScreen hereda de UMiUserWidget, y BP_MainMenuScreen hereda de UMainMenuScreen). De esa forma la clase en C++ puede tener referencias a todos los componentes que necesites acceder desde C++, y después en el BP podés tener otros componentes que hagan falta para acomodar los elementos. Ej, podés tener una variable UTextBox con BindWidget en C++ que te obliga a tener un TextBox en el widget, y en el widget podés poner el TextBox en cualquier punto de la jerarquía.

¡Podemos usar interfaces en C++ tambien!.


Recordá que está la opción de usar una interfaz también, para mi no es ideal porque tiene ciertas limitaciones y la forma de usarlas en C++ es medio rara, pero si por alguna forma no podés crear una clase propia para GameMode siempre podés crear una interfaz y trabajar con eso.



Bueno aqui termino este post, la información obtenida desde un grupo de facebook llamada Unreal Engine en Español,
Las personas que hablaron fueron Ariel gimenez haciendo las preguntas y Diego Juodziukynas respondiendo

dejo el link por si quieren verla.













No hay comentarios.:

Publicar un comentario