puerts UE 插件版本演进全解:从 v1.0.0 到 v1.0.9 的功能演进、架构选择与稳定性加固
2026/9/17 8:26:32 网站建设 项目流程

puerts UE 插件版本演进全解:从 v1.0.0 到 v1.0.9 的功能演进、架构选择与稳定性加固

【免费下载链接】puertsPUER(普洱) Typescript. Let's write your game in UE or Unity with TypeScript.项目地址: https://gitcode.com/GitHub_Trending/pu/puerts

本文基于 unreal/changelog.md 完整梳理 puerts 在 Unreal 引擎侧的版本演进脉络:v1.0.0 奠定的虚拟机启动、反射访问、模板绑定三大基石,v1.0.1 引入的多线程安全与蓝图 mixin,v1.0.5 落地的 iOS/wasm 与 pesapi,到 v1.0.9 对 UE 5.6 的兼容与ToFString性能优化。读完你可以按版本快速判断插件能力边界,并结合源码理解每项特性与修复的底层实现位置。

插件结构:读懂 Changelog 背后的模块划分

unreal/changelog.md中反复出现的概念——JsEnv、静态绑定、声明生成、mixin、puerts.Gen——对应的是 puerts UE 插件的若干模块。查看 Puerts.uplugin 可以看到插件包含 6 个模块:

模块类型LoadingPhase职责(结合 Changelog 语境)
WasmCoreRuntimePreDefaultv1.0.5 引入的 iOS / quickjs wasm 支持基础
JsEnvRuntimePreDefault虚拟机核心:FJsEnv、容器/委托/结构体包装、模块加载(v1.0.3 的DefaultJSModuleLoader即在其中)
DeclarationGeneratorEditorDefault*.d.ts声明生成(Changelog 中大量 "d.ts" 修复项的归属)
ParamDefaultValueMetasProgramPostConfigInitv1.0.7 提到的InitParamDefaultMetas.inl默认值元信息头文件生成
PuertsRuntimePostEngineInitv1.0.4 从更早期改为PostEngineInit(Changelog v1.0.4 变更项)
PuertsEditorEditorPostEngineInit编辑器按钮、蓝图生成、TypeScript 监听编译

源码目录unreal/Puerts/Source/JsEnv/Private/下按职责拆分了JsEnv.cppJsEnvImpl.cppContainerWrapper.cppDelegateWrapper.cppFunctionTranslator.cppPropertyTranslator.cppTypeScriptBlueprint.cpp等文件,Changelog 中每个修复项基本都能在这些文件中找到落点。

版本里程碑速览

v1.0.0(2022年4月8日):奠定四大基础能力

v1.0.0 是 UE 版 puerts 的正式起点,定义了此后所有版本的演进方向:

  • 在 UE 下启动一个或多个 JavaScript 虚拟机的能力;
  • 通过反射访问 UE 反射 API(标注了UCLASSUPROPERTYUFUNCTIONUSTRUCTUENUM的 C++ 类,以及所有蓝图)的能力;
  • 通过模板绑定功能访问普通 C++ API 的能力;
  • 根据反射及模板绑定声明生成对应 TypeScript(.d.ts)的能力;
  • 通过DYNAMIC_DELEGATE、静态绑定的std::function让 UE 引擎调用脚本函数的能力;
  • 通过"继承引擎类"功能提供被 UE 引擎访问脚本逻辑的能力。

v1.0.1(2022年6月30日):多线程安全 + 蓝图 mixin + 性能

这一版是"能力扩张最猛"的一版,核心新增:

  • 多线程安全(即源码中THREAD_SAFE宏体系,Changelog v1.0.9 的 Isolate 修复正是该特性的后续加固);
  • 蓝图 mixin 功能(对应unreal/doc/unreal/zhcn/mixin.md的主题);
  • 原生类型强校验、静态绑定支持默认值/静态变量/const char*/const TCHAR*参数,数组与std::string指针映射到 TS 的$Ref<T>
  • blueprint.loadblueprint.unloadblueprint.tojsAPI;
  • GC 相关接口IdleNotificationDeadlineRequestMinorGarbageCollectionForTestingRequestFullGarbageCollectionForTesting
  • FNameArrayBuffer表达,优化字符串字面值FName传输;
  • 模块的 search 与 load 阶段拆分,官方记录"某大型项目实测加载性能提升3倍";
  • Puerts.Gen增加STRUCTENUMALL参数,以及ts_file_versions_info.json的版本号处理。

关键变更:非编辑器不调用 TS 构造函数;原生类型改为强校验;UStructStaticClass在 TS 声明中改为StaticStruct(与 C++ 对齐)。

v1.0.2(2022年9月8日):移动端 Node.js 与静态绑定增强

  • 手机 nodejs 后端支持(移动端轻量部署路线);
  • 静态绑定:bound array(如int ba[10])字段、void*、仅声明无定义类注册、"重载+默认参数"、script typeconst T*const char*通过ArrayBuffer传递、std::function函数签名声明生成、ExtensionMethod(类 C# 扩展方法)、TSharedPtr、运行时获取typeid
  • 自创建的 JsEnv 支持代码热刷新;nodejs 版本支持代码热刷新;
  • 优化:BackingStore 封装带来编辑器下结构体 GC 优化;JsEnv.Start统一改为通过require加载,使初始脚本与其他脚本享有同样的 debug/热刷新待遇;增量生成蓝图的 ue.d.ts 声明,解决业务连带资源过多导致生成过慢的问题。

修复项中有价值的信号:开启 ThreadSafe 后由 TS 触发 UE GC 可能导致死锁(v1.0.9 的 Isolate 修复是其同族问题的延续);DynamicInvoker多线程访问问题;容器/非 POD UStruct 引用参数用$ref(undefined)传递的内存泄漏。

v1.0.3(2023年2月2日):工程化与编辑器体验

  • UE 类型对应的 JS 类型增加类型名称(编辑器全路径),便于堆栈 dump 分析;
  • 静态绑定void*参数支持任意原生对象;UDataTableFunctionLibrary::Generic_GetDataTableRowFromName静态绑定;
  • 手动删除蓝图后重启自动生成;
  • puerts::Objectpuerts::Function加入 JsEnv 生命周期跟踪(降低使用难度,为 v1.0.5/v1.0.6 的监听机制铺路);
  • cjs/mjs 配合优化:package.json"type": "module"指定 ESM 模块,ESM 中可加载.cjs
  • Puerts.Gen FULL蓝图全量生成;默认生成所有 struct 声明;
  • 控制台命令puerts lspuerts compile
  • 编辑器下 quickjs 后端默认用 dll 版本,去掉该后端下不能在业务模块静态声明的限制;
  • 增加运行时 JavaScript 路径配置;优化大量代理蓝图与 ts 代码的启动速度。

v1.0.4(2023年6月19日):性能与行为变更

新增:容器GetRef支持LinkOuter;默认添加 UObjectIsA的静态绑定;setTimeout/setInterval支持arguments;静态绑定加入V8 fast api callPUERTS_FORCE_CPP_UFUNCTION选项(JS 调用 JS 实现的蓝图方法时不再绕引擎段);反射支持TFieldPath;栈生命周期原生 Buff 转 JSArrayBuffer(fix #1360)。

优化:清理大部分 UE5 deprecated API 使用;instanceof不走 TS 提升静态绑定性能(#1246);对象IsUnreachable也作为无效状态;push 对象到 JS 的阶段即确定引用方向,简化逻辑并提升性能。

行为变更(升级需重点评估):

  • 蓝图静态方法第一个参数为__WorldContext时,调用 JS 忽略该参数(#1210);
  • makeUClass声明为@deprecated
  • Puerts 模块 LoadingPhase 改为PostEngineInit,不再支持 overrideGameInstance.ReceiveInit(v1.0.5 再次确认"不支持 override GameInstance.ReceiveInit");
  • 继承引擎类的 TS 类中,成员变量若为UActorComponent子类,将自动创建组件而非仅添加变量——构造函数无法访问 Component,初始化建议放ReceiveBeginPlay,层级调整需在生成的代理蓝图上手动修改。

v1.0.5(2023年8月31日):iOS/wasm 与 pesapi 体系

这一版打开了跨平台与高性能 API 两个方向:

  • iOS 以及 quickjs 后端的 wasm 实现
  • FJsObject添加 JsEnv 生命周期监听;puerts.Object补拷贝构造与赋值的生命周期监听;
  • Visual Studio 下支持 TypeScript 监听与自动蓝图/js 生成;
  • @uproperty.attach设置 Component 层次;
  • 支持单独设置某个虚拟机的max-old-space-size,增量分析编译虚拟机内存增加到 2G;
  • 声明生成按钮改为 puerts 按钮:除生成*.d.ts外也拷贝系统 js 文件;
  • puerts.toDelegate自动管理生命周期;
  • pesapi 体系:addon 支持、类型信息支持、WITHOUT_PESAPI_WRAPPER下 dll 链接方式、直接使用 V8 API、V8 fast api call、pesapi_create_array/pesapi_is_array/pesapi_get_array_length
  • macOS arm64 支持;quickjs 版本支持 html5 打包。

重要变更:配置类别更名Engine Class Extends Mode->Default JavaScript Environment;Typing 目录调整到 Project 下;quickjs 编辑器下默认使用静态链接(影响较大:用 quickjs 时不能在 JsEnv 外使用静态绑定);ReactUMG 不再随 Puerts 发布。

v1.0.6(2024年1月11日):静态绑定架构重构与 ESM 扩展

新增特性:

  • 通过赋值清空JsObject
  • UsingCrossModuleCppType,避免不同模块引用同一个类typeid不同的问题;
  • 静态绑定支持原生函数中跑异常(线程本地存储与异常两种实现,前者有侵入性,后者不能跨动态库);
  • 容器添加[Symbol.iterator]支持;
  • puerts::ObjectSetWeakAndOwnBy方法,规避循环引用;
  • 静态绑定新增MethodProxyPropertyProxy,解决多重继承 virtual public 静态绑定下子类对象调用父类方法时this指针错误的问题;
  • 静态绑定从 Function 数据获取 this 的选项GetSelfFromData
  • UE 5.3 兼容
  • v8 后端扩展 ESM 支持:引用 ue/cpp 模块、继承 ue 类支持 ESM(*.mts);
  • TArray.Add()变参函数(#1513)。

优化:v8 与 UE 字符串传递默认使用 UTF16 避免编码转换(为 v1.0.9 的ToFString直拷优化打下基础);重构静态绑定支持同时使用多种后端;puerts名字空间加_qjs后缀支持;默认打开 UE 绕行优化(#1537);容器及纯 C++ 类型改用InstanceTemplate()->NewInstance实现FindOrAdd(#1496);timer 实现优化(#1506)。

变更:内部GetJsObject改私有;v8 编译参数v8_use_external_startup_data改为 false,去掉SnapshotBlob.h(#1478)。

v1.0.6p1(2024年1月16日)单独修复"待结束的 timer 回调中设置的 timer 不生效"的问题。

v1.0.7(2024年6月25日):可配置性增强

  • 静态绑定的 Register 支持自定义析构;
  • 新增宏允许 TS 不持有 UObject(#1660);
  • JsEnv.Build.cs增加KeepUObjectReference配置,支持 JS 不强引用 UObject——对应源码 JsEnv.Build.cs 中的bKeepUObjectReference成员;
  • JsEnv.Build.cs增加SingleThreaded选项,指定 v8 别开线程池——对应源码中SingleThreaded成员,为 true 时改变 V8 平台调度方式(源码 JsEnv.Build.cs);
  • 支持 V8 10.6.194(该版本在 v1.0.9 因某些平台不稳定被移除,见下文)。

优化侧多项与"声明生成增量"相关:只在有文件更改时广播(#1637);插件蓝图类生成到ue.d.ts;静态函数每次调用查两次 hash 表的问题修复(#1654);导出 C++ 类 Interface 函数(#1681);生成默认值元信息头文件InitParamDefaultMetas.inl并保证顺序,避免每次重编FunctionTranslator.cpp;蓝图中变量顺序与 TS 文件定义顺序保持一致(#1740);去除bEnableUndefinedIdentifierWarnings依赖,可在 UE 5.3+ 下开 PCH;默认 tsconfig 添加useDefineForClassFields: false,优化 V8 8.4/9.4 性能。

修复项覆盖:UE 5.3GenericPlatformProcess编译错误、静态绑定puerts::Object赋空仍持有 context 引用、mixin 基类下 PIE 二次启动崩溃、PaddingKill对象在虚拟机释放未回收导致 UE GC 崩溃(#1645)、AddToDelegate区分 Single/MultipleDelegate 解决单播变多播、asio 符号冲突与 C++20 编译错误等。

v1.0.8(2025年3月26日):模板绑定能力补齐与 UE 5.5

  • 容器添加UE.BuiltinDouble(#1775);
  • v8 后端支持 bytecodev8 后端添加 WebSocket 支持
  • 支持 Editor Only Properties(_EditorOnly后缀,#1802);支持 UE 5.5
  • 模板绑定支持 getter/setter;UE 5.x 为FHitResult::GetActor增加模板绑定;
  • FVector等系统 USTRUCT 改用模板绑定,解决 UE5 下精度丢失问题(#1904)——这是向量类型浮点精度问题的根治方案;
  • 支持只有 setter 的属性;支持加载 Context 目录外的蓝图(#1962)。

优化与工程改进:esm 模块文件重复读取修复(#1779);new/Class.Load/Class.Find/Class.StaticClass增加非法 UStruct 关联检查;模板绑定用FObjectCacheNode的 UserData 减少原生 C++ map 插入/删除;自动从 Plugin 目录拷贝 .d.ts 到 Typing 目录,避免重复维护(#1908);最小化std::string使用;为无构造函数的原生 C++ 绑定在 TS 声明中加抽象标记(#1971);UECPP模块添加__esModule=false

行为变更:移除FJsEnv::Start直接 Eval 脚本的能力;UStruct 指针为nullptr时返回 JSnull,UObject 与纯 C++ 对象改为返回null而非undefined(#1834)——依赖undefined判空的业务代码升级时需检查。

Bug 修复密集且多为模板绑定边界:const script_type*参数崩溃(关联 #1793)、返回std::string&触发移动构造、const ustruct*匹配多个特化导致 C2752(#1917)、const SomeClass&默认值读取已释放栈变量(#1924)、mixininherit=true时蓝图组件层次未继承(#1985)、unhandledRejection期间清理 WeakMap 防止内存缓慢释放(#1991)、quickjs 默认栈大小从 256KB 提升到 1MB(例如运行 tsc 时防栈溢出)。

v1.0.9(2025年7月15日):UE 5.6 兼容与字符串路径优化

  • UE 5.6.0 兼容
  • ToFString()优化为直接拷贝 UTF-16 内存(#2010):源码见 V8Utils.cpp,非 QuickJS 路径下通过v8::String::Write()把字符串内容直写进FStringTArray<TCHAR>缓冲区,省去中间std::string/UTF-8 往返;QuickJS 后端仍走 UTF-8 路径;
  • 移除 v8 10.6.194 支持(某些平台不稳定);
  • 修复 macOS ARM64 上 Node.js 后端编译错误;
  • THREAD_SAFE开启时修复UDynamicDelegateProxy::ProcessEvent中潜在访问无效Isolate(fix #2045)——可对照源码 DynamicDelegateProxy.cpp:ProcessEvent内用v8::Locker进入 Isolate,并先DynamicInvoker.Pin()Owner.IsValid()双重校验;
  • THREAD_SAFE下修复 C++ 持有的 JS 函数引用与虚拟机生命周期不一致导致的崩溃(fix #2048);
  • 修复 mixin 覆写、但蓝图未声明的参数化事件调用崩溃(fix #1947);
  • d.ts 生成错误(#2081);
  • 清除 mixin 拷贝的父类函数的EInternalObjectFlags::Native标志(fix #2118)——该标志影响函数调用路由,残留会导致 mixin 覆写被跳过;
  • UE.Object.Load收到非法ObjectPath时防止意外触发FlushAsyncLoading(#2119);
  • 修复异步加载场景下继承 UE 类的 JS 绑定失败导致回调丢失;
  • 修正静态绑定中含容器类(如TArray)的std::function参数自动生成的 TS 声明(#2130)。

源码视角:Changelog 高频主题的实现位置

字符串传输:UTF-16 直拷的两代优化

Changelog 中 v1.0.6 的"v8 和 UE 字符串传递默认使用 UTF16 避免编码转换"与 v1.0.9 的ToFString()直拷是同一优化链。V8Utils.cpp 中ToV8String在 v8 路径用NewFromTwoByte(TCHAR_TO_UTF16(...)),QuickJS 路径退化为 UTF-8;ToFString则先ToString再按长度一次性AddUninitialized分配并Write直填,注释明确说明参考了v8::String::Value()的实现。委托绑定(DelegateWrapper.cpp 的BindUFunction)等高频路径都经由ToFString转换参数名,该优化直接作用于 JS 与 C++ 互调的热路径。

多线程安全:THREAD_SAFE 宏与 Isolate 保护

v1.0.1 引入多线程安全后,v1.0.9 的两个修复(#2045、#2048)都是该特性的收尾加固。构建系统层面,JsEnv.Build.cs 会根据ThreadSafe开关注入THREAD_SAFE/NOT_THREAD_SAFE宏(第 64 行),同时新增的SingleThreaded选项(v1.0.7)控制 V8 是否开线程池、KeepUObjectReference控制 JS 是否强引用 UObject,三者在同一 Build.cs 中集中管理,升级或排查多线程问题时可直接从该文件入手。

模板绑定与静态绑定:v1.0.8 之后的主线

v1.0.8 把FVector等系统 USTRUCT 迁到模板绑定(#1904)、为模板绑定补齐 getter/setter 支持,意味着"反射绑定(UObject/蓝图)+ 模板绑定(普通 C++ 与关键系统结构体)"的双轨结构定型。修复项密集指向模板绑定边界条件(const T*特化冲突、栈生命周期默认值、$Ref<T>映射),升级时如遇模板绑定编译错误或精度问题,可优先在 unreal/Puerts/Typing 声明文件与 Changelog 对应 fix 编号之间做比对。

升级检查清单(按 Changelog 变更项整理)

  • v1.0.4 起:Puerts 模块改为PostEngineInitGameInstance.ReceiveInit无法 override;TS 类中UActorComponent子类成员自动创建组件,构造函数中不要再手动 CreateComponent 或在构造函数内访问组件;
  • v1.0.5 起:quickjs 编辑器下默认静态链接,JsEnv 外不能再使用静态绑定;ReactUMG 需自行安装;配置项名称Default JavaScript Environment
  • v1.0.7 起:可用KeepUObjectReference/SingleThreaded/自定义析构等构建选项精细调整 JS 对象持有与 V8 线程行为;
  • v1.0.8 起:UStruct/UObject 的nullptr统一返回null(不再是undefined);FJsEnv::Start不再支持直接 Eval 脚本,脚本一律经 require 加载;UE/CPP模块__esModule=false
  • v1.0.9 起:v8 10.6.194 不再受支持,使用旧版 V8 的工程需按当前仓库支持的 V8 版本升级;UE 5.6 用户可直接采用。

Changelog 中的编号(如 #2045、#1947)对应上游 issue 跟踪;本文所有版本号、日期与条目均取自 unreal/changelog.md 原文,源码证据均出自unreal/Puerts/Source/下当前仓库实际存在的文件,可作为升级决策与故障定位的交叉验证依据。

【免费下载链接】puertsPUER(普洱) Typescript. Let's write your game in UE or Unity with TypeScript.项目地址: https://gitcode.com/GitHub_Trending/pu/puerts

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询