wbsyb 发表于 2023-8-15 15:48

UE5 PuerTS学习与实践

在游戏引擎语境中,脚本语言是高级、相对容易使用的编程语言,可供用户便利地使用引擎经常用到的功能。借助于脚本语言,法式的开发者和使用者能够便利的定制一个现存的游戏。
对比更改原生法式代码,需要从头编译及链接法式,脚本语言主要有以下优势:直译、轻量、撑持快速迭代、便利易用。



虚幻引擎C++编码与脚本语言编码对比

在使用虚幻引擎进行开发的过程中,UE 的蓝图脚本可以便利的改削逻辑,从头编译蓝图然后即可看到改动后的效果,这对功能验证和开发效率的提升辅佐非常大。对于打包后的虚幻引擎法式,需要有一个运行时的脚本系统,来实现一些定制化的逻辑,由于虚幻引擎的蓝图脚本系统不撑持运行时使用,因此可以选择 Lua、Python、TypeScript 等脚本语言实现相应的功能。
1、PuerTS 简介&插件安装

PuerTS 是游戏引擎下的 TypeScript 编程解决方案,它提供了一个 JavaScript 运行时,提供通过TypeScript访谒宿主引擎的能力。Puerts 默认导入了所有反射 api,因此在 UE 蓝图里能调用的引擎 API,在 Typescript/JavaScript 环境都可以调用。有了这样一套可以在运行时使用的接口,便可以拿来在运行时编排逻辑。
要使用 PuerTS,首先创建一个 C++ 版本的 UE 工程。
PuerTS 的安装使用官方教程斗劲完善,工程中使用该插件,参照 puerts/install.md at master · Tencent/puerts · GitHub链接中下载源码,注意下载完成后,仅拷贝该目录下的 Puerts 到虚幻引擎项目的 Plugins 中即可。


本工程测试时使用 Unreal 5.0.3 版本,因此又下载了一个适配的 V8 。在官方提供的链接中,跳转后下载编译好的版本。




下载完成解压后,将该目录下的 v8 文件夹整个拷贝到 YourProject/Plugins/Puerts/ThirdParty 目录下。完成后在 .uproject 上右键选择生成 sln 。


2、编写测试代码

2.1、编写 c++ 相关的代码

完成后在 YourProject.Build.cs 中添加相关的依赖模块:
PrivateDependencyModuleNames.AddRange(new string[] { ”Puerts”, ”JsEnv” });添加完成后,在 GameMode.h 文件中添加一个执行脚本代码的函数。官方样例中给了一个在 BeginPlay 函数中生成 FJsEnv,然后执行对应脚本的例子。这里不想在一开始就执行脚本,想要在某个时机(例如按钮按下)执行所需的脚本。所以写了一个 ExecuteScript 函数,接受一个脚本文件,以及传来的一组参数。同时为了能够以调试模式执行脚本,增加了一个布尔参数。
此中,以调试模式执行脚本参考vscode_debug | PuerTS(普洱TS)和 Puerts Inspector指南(一)在UE4和Unity里调试Javascript 。
// .h 文件
public:
        UFUNCTION(BlueprintCallable)
        void ExecuteScript(FString ScriptPath, TMap<FString, UObject*> InArgs, bool bWithDebug);

        TSharedPtr<puerts::FJsEnv> JsEnv;

// .cpp 文件
void ALearnPuerTSGameModeBase::ExecuteScript(FString ScriptPath, TMap<FString, UObject*> InArgs, bool bWithDebug)
{
        if (JsEnv)
        {
                JsEnv.Reset();
        }

        if (bWithDebug)
        {
                JsEnv = MakeShared<puerts::FJsEnv>(std::make_unique<puerts::DefaultJSModuleLoader>(TEXT(”JavaScript”)), std::make_shared<puerts::FDefaultLogger>(), 8080);
                JsEnv->WaitDebugger();
        }
        else
        {
                JsEnv = MakeShared<puerts::FJsEnv>();
        }

        if (JsEnv)
        {
                TArray<TPair<FString, UObject*>> RealArgs;
                for (const TPair<FString, UObject*>& Kvp : InArgs)
                {
                        if (Kvp.Value != nullptr)
                        {
                                const TPair<FString, UObject*> Item = TPair<FString, UObject*>(Kvp.Key, Kvp.Value);
                                RealArgs.Add(Item);
                        }
                }
                FString ScriptBaseName = FPaths::GetBaseFilename(ScriptPath);
                JsEnv->Start(ScriptBaseName, RealArgs);
        }
}
2.2、初始化编写脚本代码的环境

写完 C++ 相关的函数后,编译 sln 。然后发现并没有像官方提供的一个 Demo 那样有写 TS 代码的处所,搜索后发现需要做一些写 TS 代码初始化相关的操作:
cmd 或 powershell 打开项目目录下: Plugins\Puerts ,并执行如下命令
node enable_puerts_module.js
该命令感化:
将 Puerts 下的 Content/Javascript 拷贝到 工程目录下的 Content 下
创建并初始化 tsconfig 文件 (内容来源于 enable_puerts_module.js 中 )
创建并初始化 DefaultPuerts.ini 到项目目录 Config 下(内容 AutoModeEnable=True )
在项目根目录创建 TypeScript 目录
npm 安装 Puerts_Editor 的依赖包初始化相关操作的教程中提到去到工程根目录 cmd 或 powershell ,运行 npm init -y 创建一个默认的 package.json ,本项目只是学习使用 TS,不使用 ReactUMG,不必做这一步。
颠末以上操作后,YourProject 目录下会生成一个 TypeScript 目录,在里面新建一个 LearPuerTsQuickStart.ts 脚本文件,然后输入一些内容:
import * as UE from &#39;ue&#39;
import {$ref, $unref, $set, argv, on, toManualReleaseDelegate, releaseManualReleaseDelegate, blueprint} from &#39;puerts&#39;;

let GameMode = argv.getByName(”GameMode”) as UE.LearnPuerTSGameModeBase;
let MyWorld = GameMode.GetWorld();
if(GameMode)
{
    UE.KismetSystemLibrary.PrintString(MyWorld,”脚本中获取到GameMode”,true,true,new UE.LinearColor(1.0,0.0,0.0,1.0),5.0,”None”);
}2.3、UE Editor中的设置

完成后,打开 UE 编纂器,设置 World Setting 中的 GameMode 为我们写的 LeranPuerTsGameMode。
创建一个 UMG,此中创建两个按钮,分袂为


我们目前只使用执行脚本来测试我们写的脚本是否能被执行。在 UMG 中添加如下逻辑:


游戏一开始,获取到相应的 GameMode 对象,然后在”执行脚本”按钮后,将”ArgsPassToScript”变量添加一个
<”GameMode”, GameModeObject>这样一个键值对,传递给脚本代码使用。此中”ArgsPassToScript”是在 UMG 中创建的一个键为 FString,值为 UObject 的 Map。
然后在适当的位置创建该 UMG ,并AddtoViewPort。
运行起来法式后,点击执行脚本按钮,即可在左上角发现输出的内容,脚本被成功执行。


3、编纂器&打包后运行时更新脚本代码

执行脚本按钮和调试执行脚本按钮调用的 c++ 函数中先遏制掉了旧的虚拟机,然后新建了一个虚拟机读入 JavaScript 脚本,因此只要在脚本文件中写入新的代码逻辑,点击按钮即可看到新的逻辑生效。
if (JsEnv)
{
        JsEnv.Reset();
}

if (bWithDebug)
{
        JsEnv = MakeShared<puerts::FJsEnv>(std::make_unique<puerts::DefaultJSModuleLoader>(TEXT(”JavaScript”)), std::make_shared<puerts::FDefaultLogger>(), 8080);
        JsEnv->WaitDebugger();
}
else
{
        JsEnv = MakeShared<puerts::FJsEnv>();
}4、编纂器&打包后运行时调试脚本代码

关于使用Puerts插件调试 JS 代码,Puerts Inspector指南(一)在UE4和Unity里调试Javascript 一文中有详细的图文指南和道理解释,参照文章中的教程即可,注意调试端口不要和其它法式冲突了。
参考


[*]^游戏引擎架构 第2版
[*]^普洱TS!Write your game with TypeScript in UE or Unity.  https://github.com/Tencent/puerts
[*]^自创建虚拟机的调试 https://puerts.github.io/docs/puerts/unreal/vscode_debug
[*]^Puerts Inspector指南(一)在UE4和Unity里调试Javascript https://zhuanlan.zhihu.com/p/359598262
[*]^跟我用TypeScript做一个FPS游戏 https://zhuanlan.zhihu.com/p/346531865
[*]^Puerts & ReactUMG 环境搭建(二) https://zhuanlan.zhihu.com/p/397369095

xiaohongchen58 发表于 2023-8-15 15:49

厉害👍
页: [1]
查看完整版本: UE5 PuerTS学习与实践