[UE4]Puerts Notes
keywords: UE4, Puerts Notes
Common
Examples
Unreal example: How to debug TypeScript based on Unreal PuerTS in IntelliJ IDEA
https://github.com/dawnarc/PuertsGame
C++ server example:《c++游戏服务器嵌入v8 js引擎胎教级教程》配套代码
https://github.com/chexiongsheng/v8_embedding_test
Performance
Benchmarking of C++, SLUA, Unreal.js, Puerts
https://github.com/Tencent/puerts/issues/443
- The speed of interacting with C++ or UE4 Blueprint:
Puerts
is 11 timessLua
, 5 timesUnreal.js
. - The speed of running pure script:
Puerts
is 67 timessLua
, has the same performance ofUnreal.js
. - Pure C++ vs. Pure TypeScript (
PuerTS
): C++ is 3.5 timesPuerTS
, as a comparison, C++ is twice performance of nativing Blueprint of UE4.
Extension: how to add(bind) other Unreal API in ue.d.ts
Add UUserWidget::GetWidgetFromName()
in ue.d.ts:
#include "CoreMinimal.h"
#include "Binding.hpp"
#include "UEDataBinding.hpp"
#include "Blueprint/UserWidget.h"
UsingUClass(UObject);
UsingUClass(UClass);
#if !defined(ENGINE_INDEPENDENT_JSENV)
UsingUClass(UWorld); // for return type
UsingUClass(USceneComponent);
UsingUClass(UActorComponent);
UsingUClass(UUserWidget);
UsingUClass(UWidget);
#endif
struct AutoRegisterForUE
{
AutoRegisterForUE()
{
puerts::DefineClass<UObject>()
#if ENGINE_MAJOR_VERSION >= 4 && ENGINE_MINOR_VERSION >= 23
.Method("CreateDefaultSubobject",
SelectFunction(UObject * (UObject::*) (FName, UClass*, UClass*, bool, bool), &UObject::CreateDefaultSubobject))
#else
.Method("CreateDefaultSubobject", SelectFunction(UObject * (UObject::*) (FName, UClass*, UClass*, bool, bool, bool),
&UObject::CreateDefaultSubobject))
#endif
.Method("GetName", SelectFunction(FString(UObjectBaseUtility::*)() const, &UObjectBaseUtility::GetName))
.Method("GetOuter", MakeFunction(&UObject::GetOuter))
.Method("GetClass", MakeFunction(&UObject::GetClass))
#if !defined(ENGINE_INDEPENDENT_JSENV)
.Method("GetWorld", MakeFunction(&UObject::GetWorld))
#endif
.Register();
#if !defined(ENGINE_INDEPENDENT_JSENV)
puerts::DefineClass<USceneComponent>()
.Method("SetupAttachment", MakeFunction(&USceneComponent::SetupAttachment))
.Register();
puerts::DefineClass<UActorComponent>()
.Method("RegisterComponent", MakeFunction(&UActorComponent::RegisterComponent))
.Register();
puerts::DefineClass<UUserWidget>()
.Method("GetWidgetFromName", SelectFunction(UWidget* (UUserWidget::*) (const FName&) const, &UUserWidget::GetWidgetFromName))
.Register();
#endif
}
};
AutoRegisterForUE _AutoRegisterForUE__;
Binding
Dynamic delegate VS Call function directly
https://github.com/Tencent/puerts/issues/749
How to call Blueprint Function from TypeScript
let Name = $ref("");
const TestBlueprint = blueprint<typeof UE.Game.Blueprints.BP_MyActor.BP_MyActor_C>('/Game/Blueprints/BP_MyActor.BP_MyActor_C');
TestBlueprint.Fun_GetMyName("GetMyName", this, Name);
Issues
Crash on startup : AsyncLoadingThread.RecursionNotAllowed.Increment() == 1
Packaged application startup failed with pop error (works right in editor):
Assertion failed: AsyncLoadingThread.RecursionNotAllowed.Increment() == 1 [File:D:/Build/++UE4/Sync/Engine/Source/Runtime/CoreUObject/Private/Serialization/AsyncLoading.cpp] [Line: 3992]
Solution:
Load object in ReceiveBeginPlay
instead of loading object in Constructor.
TArray.Get returns value type
C++
USTRUCT(BlueprintType)
struct FMyStruct
{
GENERATED_USTRUCT_BODY()
UPROPERTY()
FString ID;
}
TypeScript:
public List: UE.TArray<UE.FMyStruct>;
Constructor()
{
this.List = UE.NewArray(UE.FMyStruct);
this.List.Add(new UE.FMyStruct);
}
example:
let Data = List.Get(0);
Data.ID = "foo";
Data
is a copy of List.Get(0)
(value type), not a reference type, so Data.ID = "foo";
can’t interpolate the value which was inside the List
. Use GetRef()
instead of Get()
if want the reference.
Reference:
https://github.com/Tencent/puerts/issues/703
Error: can not find XXX
Error on playing game
Puerts: Display: (0x000001D0EEC7A250) Bind module [Character/TS_AnimInstance]
Puerts: Error: (0x000001D0EEC7A250) load module [Character/TS_AnimInstance] exception D:\MyProj\Content\JavaScript\puerts\modular.js:96: Error: can not find [Character/TS_AnimInstance]
Error: can not find [Character/TS_AnimInstance]
at require (D:\MyProj\Content\JavaScript\puerts\modular.js:96:30)
Caused by:
There’s some compilation error in TypeScript source caused by C++ interface, e.g. a function invoked in TS was removed in C++. Fix the compilation error then re-generate ue.d.ts
.
Solution:
Fix the compilation error. Build C++ project if C++ source was modified.
You’d better close editor and remove tsconfig.json
, then re-execute command node enable_puerts_module.js
.
Or generate ue.d.ts
, then restart editor, then regenerate ue.d.ts
again.
Crash: internal::FixStaleLeftTrimmedHandlesVisitor::VisitRootPointers()
Crash callstack:
PuertsTestError: === Critical error: ===
PuertsTestError:
PuertsTestError: Fatal error!
PuertsTestError:
PuertsTestError: Unhandled Exception: EXCEPTION_ACCESS_VIOLATION reading address 0xffffffffffffffff
PuertsTestError:
PuertsTestError: [Callstack] 0x00007ff74197ccb9 Test.exe!v8::internal::FixStaleLeftTrimmedHandlesVisitor::VisitRootPointers() []
PuertsTestError: [Callstack] 0x00007ff74192193f Test.exe!v8::internal::HandleScopeImplementer::IterateThis() []
PuertsTestError: [Callstack] 0x00007ff741971c8e Test.exe!v8::internal::Heap::IterateStrongRoots() []
PuertsTestError: [Callstack] 0x00007ff741971a72 Test.exe!v8::internal::Heap::IterateRoots() []
PuertsTestError: [Callstack] 0x00007ff741b58632 Test.exe!v8::internal::ScavengerCollector::CollectGarbage() []
PuertsTestError: [Callstack] 0x00007ff74197a1b2 Test.exe!v8::internal::Heap::Scavenge() []
PuertsTestError: [Callstack] 0x00007ff741974829 Test.exe!v8::internal::Heap::PerformGarbageCollection() []
PuertsTestError: [Callstack] 0x00007ff741968d53 Test.exe!v8::internal::Heap::CollectGarbage() []
PuertsTestError: [Callstack] 0x00007ff741967084 Test.exe!v8::internal::Heap::AllocateRawWithRetryOrFail() []
PuertsTestError: [Callstack] 0x00007ff741984bed Test.exe!v8::internal::Factory::CopyJSObjectWithAllocationSite() []
PuertsTestError: [Callstack] 0x00007ff741984a81 Test.exe!v8::internal::Factory::CopyJSObject() []
PuertsTestError: [Callstack] 0x00007ff7419c3257 Test.exe!v8::internal::ApiNatives::InstantiateFunction() []
PuertsTestError: [Callstack] 0x00007ff7419c35a5 Test.exe!v8::internal::ApiNatives::InstantiateObject() []
PuertsTestError: [Callstack] 0x00007ff741aa2308 Test.exe!v8::internal::CustomArguments<v8::FunctionCallbackInfo<v8::Value> >::GetReturnValue<v8::internal::Object>() []
PuertsTestError: [Callstack] 0x00007ff741aa3807 Test.exe!v8::internal::Builtins::InvokeApiFunction() []
PuertsTestError: [Callstack] 0x00007ff741945a69 Test.exe!v8::internal::Execution::CallWasm() []
PuertsTestError: [Callstack] 0x00007ff741945f7b Test.exe!v8::internal::Execution::New() []
PuertsTestError: [Callstack] 0x00007ff7419298b6 Test.exe!v8::Function::NewInstanceWithSideEffectType() []
PuertsTestError: [Callstack] 0x00007ff741929240 Test.exe!v8::Function::NewInstance() []
PuertsTestError: [Callstack] 0x00007ff73b1c803d Test.exe!puerts::FJsEnvImpl::FindOrAdd() [D:\TestProj\Plugins\Puerts\Source\JsEnv\Private\JsEnvImpl.cpp:1541]
PuertsTestError: [Callstack] 0x00007ff73b0884b5 Test.exe!puerts::internal::FuncCallHelper<std::pair<UObject *,std::tuple<FName,UClass *,UClass *,bool,bool> >,0>::callMethod<UObject,UObject * (__cdecl UObject::*)(FName,UClass *,UClass *,bool,bool),0,1,2,3,4>() [D:\TestProj\Plugins\Puerts\Source\JsEnv\Public\Binding.hpp:403]
PuertsTestError: [Callstack] 0x00007ff73b185dd3 Test.exe!puerts::FuncCallWrapper<UObject * (__cdecl UObject::*)(FName,UClass *,UClass *,bool,bool),&UObject::CreateDefaultSubobject>::call() [D:\TestProj\Plugins\Puerts\Source\JsEnv\Public\Binding.hpp:464]
PuertsTestError: [Callstack] 0x00007ff741aa3250 Test.exe!v8::internal::FunctionCallbackArguments::Call() []
PuertsTestError: [Callstack] 0x00007ff741aa273f Test.exe!v8::internal::CustomArguments<v8::FunctionCallbackInfo<v8::Value> >::GetReturnValue<v8::internal::Object>() []
PuertsTestError: [Callstack] 0x00007ff741aa2abf Test.exe!v8::internal::Builtin_HandleApiCallAsFunction() []
PuertsTestError: [Callstack] 0x00007ff741aa28be Test.exe!v8::internal::Builtin_HandleApiCall() []
PuertsTestError: [Callstack] 0x00007ff74216ddbd Test.exe!Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_BuiltinExit() []
PuertsTestError: [Callstack] 0x00007ff7420ec8ec Test.exe!Builtins_InterpreterEntryTrampoline() []
PuertsTestError: [Callstack] 0x00007ff7420ec8ec Test.exe!Builtins_InterpreterEntryTrampoline() []
PuertsTestError: [Callstack] 0x00007ff7420e9ea1 Test.exe!Builtins_JSEntryTrampoline() []
PuertsTestError: [Callstack] 0x00007ff7420e9a8c Test.exe!Builtins_JSEntry() []
PuertsTestError: [Callstack] 0x00007ff741945cd3 Test.exe!v8::internal::Execution::CallWasm() []
PuertsTestError: [Callstack] 0x00007ff741945646 Test.exe!v8::internal::Execution::Call() []
PuertsTestError: [Callstack] 0x00007ff741907eeb Test.exe!v8::Function::Call() []
PuertsTestError: [Callstack] 0x00007ff73b1e04ca Test.exe!puerts::FJsEnvImpl::TsConstruct() [D:\TestProj\Plugins\Puerts\Source\JsEnv\Private\JsEnvImpl.cpp:1809]
PuertsTestError: [Callstack] 0x00007ff73b219132 Test.exe!UTypeScriptGeneratedClass::ObjectInitialize() [D:\TestProj\Plugins\Puerts\Source\JsEnv\Private\TypeScriptGeneratedClass.cpp:71]
PuertsTestError: [Callstack] 0x00007ff73b21c462 Test.exe!UTypeScriptGeneratedClass::StaticConstructor() [D:\TestProj\Plugins\Puerts\Source\JsEnv\Private\TypeScriptGeneratedClass.cpp:53]
PuertsTestError: [Callstack] 0x00007ff73cb96a6b Test.exe!StaticConstructObject_Internal() []
PuertsTestError: [Callstack] 0x00007ff7400aa368 Test.exe!UWorld::SpawnActor() []
PuertsTestError: [Callstack] 0x00007ff73ff161d3 Test.exe!UGameplayStatics::BeginDeferredActorSpawnFromClass() []
PuertsTestError: [Callstack] 0x00007ff740a474c0 Test.exe!UGameplayStatics::execBeginDeferredActorSpawnFromClass() []
PuertsTestError: [Callstack] 0x00007ff73c8f6839 Test.exe!UFunction::Invoke() []
PuertsTestError: [Callstack] 0x00007ff73cb79d8c Test.exe!UObject::ProcessEvent() []
PuertsTestError: [Callstack] 0x00007ff73b0971ec Test.exe!puerts::FFunctionTranslator::Call() [D:\TestProj\Plugins\Puerts\Source\JsEnv\Private\FunctionTranslator.cpp:259]
PuertsTestError: [Callstack] 0x00007ff73b097450 Test.exe!puerts::FFunctionTranslator::Call() [D:\TestProj\Plugins\Puerts\Source\JsEnv\Private\FunctionTranslator.cpp:205]
PuertsTestError: [Callstack] 0x00007ff741aa3250 Test.exe!v8::internal::FunctionCallbackArguments::Call() []
PuertsTestError: [Callstack] 0x00007ff741aa273f Test.exe!v8::internal::CustomArguments<v8::FunctionCallbackInfo<v8::Value> >::GetReturnValue<v8::internal::Object>() []
PuertsTestError: [Callstack] 0x00007ff741aa2abf Test.exe!v8::internal::Builtin_HandleApiCallAsFunction() []
PuertsTestError: [Callstack] 0x00007ff741aa28be Test.exe!v8::internal::Builtin_HandleApiCall() []
PuertsTestError: [Callstack] 0x00007ff74216ddbd Test.exe!Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_BuiltinExit() []
PuertsTestError: [Callstack] 0x00007ff7420ec8ec Test.exe!Builtins_InterpreterEntryTrampoline() []
PuertsTestError: [Callstack] 0x00007ff7420e9ea1 Test.exe!Builtins_JSEntryTrampoline() []
PuertsTestError: [Callstack] 0x00007ff7420e9a8c Test.exe!Builtins_JSEntry() []
PuertsTestError: [Callstack] 0x00007ff741945cd3 Test.exe!v8::internal::Execution::CallWasm() []
PuertsTestError: [Callstack] 0x00007ff741945646 Test.exe!v8::internal::Execution::Call() []
PuertsTestError: [Callstack] 0x00007ff741907eeb Test.exe!v8::Function::Call() []
PuertsTestError: [Callstack] 0x00007ff73b098408 Test.exe!puerts::FFunctionTranslator::CallJs() [D:\TestProj\Plugins\Puerts\Source\JsEnv\Private\FunctionTranslator.cpp:452]
PuertsTestError: [Callstack] 0x00007ff73b1cb5f0 Test.exe!puerts::FJsEnvImpl::InvokeTsMethod() [D:\TestProj\Plugins\Puerts\Source\JsEnv\Private\JsEnvImpl.cpp:1982]
PuertsTestError: [Callstack] 0x00007ff73b22c95f Test.exe!UTypeScriptGeneratedClass::execCallJS() [D:\TestProj\Plugins\Puerts\Source\JsEnv\Private\TypeScriptGeneratedClass.cpp:27]
PuertsTestError: [Callstack] 0x00007ff73c8f6839 Test.exe!UFunction::Invoke() []
PuertsTestError: [Callstack] 0x00007ff73cb79d8c Test.exe!UObject::ProcessEvent() []
PuertsTestError: [Callstack] 0x00007ff73b0971ec Test.exe!puerts::FFunctionTranslator::Call() [D:\TestProj\Plugins\Puerts\Source\JsEnv\Private\FunctionTranslator.cpp:259]
PuertsTestError: [Callstack] 0x00007ff73b097450 Test.exe!puerts::FFunctionTranslator::Call() [D:\TestProj\Plugins\Puerts\Source\JsEnv\Private\FunctionTranslator.cpp:205]
PuertsTestError: [Callstack] 0x00007ff741aa3250 Test.exe!v8::internal::FunctionCallbackArguments::Call() []
PuertsTestError: [Callstack] 0x00007ff741aa273f Test.exe!v8::internal::CustomArguments<v8::FunctionCallbackInfo<v8::Value> >::GetReturnValue<v8::internal::Object>() []
PuertsTestError: [Callstack] 0x00007ff741aa2abf Test.exe!v8::internal::Builtin_HandleApiCallAsFunction() []
PuertsTestError: [Callstack] 0x00007ff741aa28be Test.exe!v8::internal::Builtin_HandleApiCall() []
PuertsTestError: [Callstack] 0x00007ff74216ddbd Test.exe!Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_BuiltinExit() []
PuertsTestError: [Callstack] 0x00007ff7420ec8ec Test.exe!Builtins_InterpreterEntryTrampoline() []
PuertsTestError: [Callstack] 0x00007ff7420e9ea1 Test.exe!Builtins_JSEntryTrampoline() []
PuertsTestError: [Callstack] 0x00007ff7420e9a8c Test.exe!Builtins_JSEntry() []
PuertsTestError: [Callstack] 0x00007ff741945cd3 Test.exe!v8::internal::Execution::CallWasm() []
PuertsTestError: [Callstack] 0x00007ff741945646 Test.exe!v8::internal::Execution::Call() []
PuertsTestError: [Callstack] 0x00007ff741907eeb Test.exe!v8::Function::Call() []
PuertsTestError: [Callstack] 0x00007ff73b098408 Test.exe!puerts::FFunctionTranslator::CallJs() [D:\TestProj\Plugins\Puerts\Source\JsEnv\Private\FunctionTranslator.cpp:452]
PuertsTestError: [Callstack] 0x00007ff73b1cb5f0 Test.exe!puerts::FJsEnvImpl::InvokeTsMethod() [D:\TestProj\Plugins\Puerts\Source\JsEnv\Private\JsEnvImpl.cpp:1982]
PuertsTestError: [Callstack] 0x00007ff73b22c95f Test.exe!UTypeScriptGeneratedClass::execCallJS() [D:\TestProj\Plugins\Puerts\Source\JsEnv\Private\TypeScriptGeneratedClass.cpp:27]
PuertsTestError: [Callstack] 0x00007ff73c8f6839 Test.exe!UFunction::Invoke() []
PuertsTestError: [Callstack] 0x00007ff73cb79d8c Test.exe!UObject::ProcessEvent() []
PuertsTestError: [Callstack] 0x00007ff73b0971ec Test.exe!puerts::FFunctionTranslator::Call() [D:\TestProj\Plugins\Puerts\Source\JsEnv\Private\FunctionTranslator.cpp:259]
PuertsTestError: [Callstack] 0x00007ff73b097450 Test.exe!puerts::FFunctionTranslator::Call() [D:\TestProj\Plugins\Puerts\Source\JsEnv\Private\FunctionTranslator.cpp:205]
PuertsTestError: [Callstack] 0x00007ff741aa3250 Test.exe!v8::internal::FunctionCallbackArguments::Call() []
PuertsTestError: [Callstack] 0x00007ff741aa273f Test.exe!v8::internal::CustomArguments<v8::FunctionCallbackInfo<v8::Value> >::GetReturnValue<v8::internal::Object>() []
PuertsTestError: [Callstack] 0x00007ff741aa2abf Test.exe!v8::internal::Builtin_HandleApiCallAsFunction() []
PuertsTestError: [Callstack] 0x00007ff741aa28be Test.exe!v8::internal::Builtin_HandleApiCall() []
PuertsTestError: [Callstack] 0x00007ff74216ddbd Test.exe!Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_BuiltinExit() []
PuertsTestError: [Callstack] 0x00007ff7420ec8ec Test.exe!Builtins_InterpreterEntryTrampoline() []
PuertsTestError: [Callstack] 0x00007ff7420e9ea1 Test.exe!Builtins_JSEntryTrampoline() []
PuertsTestError: [Callstack] 0x00007ff7420e9a8c Test.exe!Builtins_JSEntry() []
PuertsTestError: [Callstack] 0x00007ff741945cd3 Test.exe!v8::internal::Execution::CallWasm() []
PuertsTestError: [Callstack] 0x00007ff741945646 Test.exe!v8::internal::Execution::Call() []
PuertsTestError: [Callstack] 0x00007ff741907eeb Test.exe!v8::Function::Call() []
PuertsTestError: [Callstack] 0x00007ff73b0986c1 Test.exe!puerts::FFunctionTranslator::CallJs() [D:\TestProj\Plugins\Puerts\Source\JsEnv\Private\FunctionTranslator.cpp:338]
PuertsTestError: [Callstack] 0x00007ff73b1caf80 Test.exe!puerts::FJsEnvImpl::InvokeJsCallback() [D:\TestProj\Plugins\Puerts\Source\JsEnv\Private\JsEnvImpl.cpp:1668]
PuertsTestError: [Callstack] 0x00007ff73b178ac4 Test.exe!UDynamicDelegateProxy::ProcessEvent() [D:\TestProj\Plugins\Puerts\Source\JsEnv\Private\DynamicDelegateProxy.cpp:23]
PuertsTestError: [Callstack] 0x00007ff73c22113f Test.exe!UITTcpLibrary::Tick() [D:\TestProj\Source\Avatar\Network\ITTcpLibrary.cpp:517]
PuertsTestError: [Callstack] 0x00007ff73c229299 Test.exe!AAvatarGameMode::Tick() [D:\TestProj\Source\Avatar\AvatarGameMode.cpp:28]
PuertsTestError: [Callstack] 0x00007ff73f9f9a3e Test.exe!AActor::TickActor() []
PuertsTestError: [Callstack] 0x00007ff73f9d60ae Test.exe!FActorTickFunction::ExecuteTick() []
PuertsTestError: [Callstack] 0x00007ff7407a0b7b Test.exe!FTickFunctionTask::DoTask() []
Caused by:
Issue of js V8
https://github.com/Tencent/puerts/issues/346
https://github.com/Tencent/puerts/issues/603
Solution:
update v8 to the latest version
https://github.com/Tencent/puerts/blob/master/doc/unreal/zhcn/install.md
Cannot find module ‘ue’ or its corresponding type declarations
Error on compiling:
Puerts: Error: (0x0000021C909052D0) Error D:/PuertsGame/TypeScript/ObjectExt.ts (1,21): Cannot find module 'ue' or its corresponding type declarations.
Puerts: Error: (0x0000021C909052D0) Error D:/PuertsGame/TypeScript/ObjectExt.ts (3,16): Invalid module name in augmentation, module 'ue' cannot be found.
Solution:
Restart editor and generate ue.d.ts
.
“There's no coming to consciousness without pain.” ― Carl Gustav Jung