En un tutorial anterior vimos como utilizar un interprete de Python en una aplicación C++, ahora podemos utilizarlo como base para utilizar un interprete de Python en nuestros proyectos de Unreal Engine. Con ello podremos utilizar código Python en nuestros juegos
Empezaremos con un proyecto C++ vacio de Unreal Engine. En el definiremos una clase para gestionar el intérprete de Python
Ya dentro del proyecto podemos crear una clase de C++ desde Tools > New C++ Class
Creamos la clase para gestionar el intérprete
Para este ejemplo vamos a definir un nodo de Unreal Engine que calculará el coseno de un angulo utilizando una función de Python
PythonInterpreter.h
#pragma once #include "CoreMinimal.h" #include "UObject/ObjectMacros.h" #include "UObject/NoExportTypes.h" #include "PythonInterpreter.generated.h" UCLASS(Blueprintable, BlueprintType) class UE5_T_PYTHON_API UPythonInterpreter : public UObject { GENERATED_BODY() public: UFUNCTION(BlueprintCallable, Category = "PythonInterpreter|math|cos") void CalculateCosineNode(const float& input, float& output); UPythonInterpreter(); ~UPythonInterpreter(); private: float calculate_cosine(const float& input); };
PythonInterpreter.cpp
#include "PythonInterpreter.h" #pragma push_macro("check") #undef check #pragma warning (push) #pragma warning (disable : 4191) #pragma warning (disable : 4591) #pragma warning (disable : 4686) #include <pybind11/embed.h> #pragma warning (pop) #pragma pop_macro("check") namespace py = pybind11; UPythonInterpreter::UPythonInterpreter() { } UPythonInterpreter::~UPythonInterpreter() { } void UPythonInterpreter::CalculateCosineNode(const float& input, float& output) { output = calculate_cosine(input); } float UPythonInterpreter::calculate_cosine(const float& input) { py::scoped_interpreter guard{}; auto math_module = py::module_::import("math"); py::object result = math_module.attr("cos")(input); return py::cast<float>(result); }
Estamos utilizando pybind11 para envolver las llamadas a funciones de Python con llamadas de c++, tendremos que incluir ciertas claúsulas alrededor de sus includes para poder utilizarlo en UE5 y evitar errores durante la la compilación.
En la función calculate_cosine creamos una instancia del intérprete antes de importar su módulo math y llamar a su función cos. Pero cada vez que llamamos a esta función un intérprete de Python es creado y el módulo math es también cargado.
Para evitar este gasto de recursos con cada llamada podemos mover la inicialización del intérprete y linkar su tiempo de vida a tiempor de vida del objeto de la clase. Después solo necesitamos tener un objeto de la clase que va a contener el intérprete y utilizar este objeto para llamar nodos que van a ejecutar código Python.
Tendremos que incluir las librerías de terceros al fichero Build.cs de nuestro proyecto con PrivateIncludePaths
Build.cs
using System.IO; using UnrealBuildTool; public class UE5_T_Python : ModuleRules { public UE5_T_Python(ReadOnlyTargetRules Target) : base(Target) { PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; bUseRTTI = true; bEnableExceptions = true; PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" }); PrivateDependencyModuleNames.AddRange(new string[] { }); PrivateIncludePaths.Add(Path.Combine(ModuleDirectory, "../UE5_T_Python/thirdparty/pybind11/include")); string python_path = @"D:\Programs\Python312"; PrivateIncludePaths.Add(Path.Combine(python_path, "include")); PublicAdditionalLibraries.Add(Path.Combine(python_path, "libs", "python312.lib")); } }
Estamos usando linkage estático con la librería de Python del sistema. Esta librería puede incluirse junto a la release y utilizar una ruta relativa al .lib, también tendremos que añadir los includes a las cabeceras de Python
Otra opción sería utilizar linkage dinámico y utilizar la librería .dll junto a una llamada de PublicDelayLoadDLLs en vez de PublicAdditionalLibraries
Ahora en el editor de Unreal podemos crear el Blueprint que recubrirá a nuestra clase PythonInterpreter para utilizarla como variable en the level
Ahora podemos crear una variable en el blueprint del nivel
Construiremos la variable y podremos usar su nodo CalculateCosineNode para calcular el coseno utilizando el módulo math de python
En la consola vemos el resultado de la ejecución del nodo
Conclusion
Con este tutorial hemos visto una manera sencilla de incluir un interprete de Python en nuestros proyectos de Unreal Engine. Puedo resultarnos muy útil si tenemos módulos de Python que no queremos portar a c++ pero aún así necesitamos utilizarlos. Ahora podemos ejecutar código Python en nuestros juegos de Unreal Engine
Tutorial files
Te puede interesar:
Ayudanos con este blog!
El último año he estado dedicando cada vez más tiempo a la creación de tutoriales, en su mayoria sobre desarrollo de videojuegos. Si crees que estos posts te han ayudado de alguna manera o incluso inspirado, por favor considera ayudarnos a mantener este blog con alguna de estas opciones. Gracias por hacerlo posible!