Puerts - Unreal User Manual
Below is a translated version of the original docs by Incanta Games. The translation is mainly done with Google Translate, but then modified by hand to try to make sense of what Google Translate is missing.
Get started using with one of two methods
Method 1: Start the virtual machine yourself
- Start one or more virtual machines as needed (such as
GameInstance
)- If multiple virtual machines are started, these virtual machines are isolated from each other.
- Start a script with the
Start
function, as the entry point of the script logic (Similar to themain
function)Start
can be passed to some data as a parameter for the script acquisition
- The script in the virtual machine can be interactive according to the rule of puerts (later chapter) and engine
UCLASS()
class PUERTS_UNREAL_DEMO_API UTsGameInstance : public UGameInstance
{
public:
TSharedPtr<puerts::FJsEnv> JsEnv;
virtual void OnStart() override {
JsEnv = MakeShared<puerts::FJsEnv>();
TArray<TPair<FString, UObject*>> Arguments;
Arguments.Add(TPair<FString, UObject*>(TEXT("GameInstance"), this));
JsEnv->Start("QuickStart", Arguments);
}
virtual void Shutdown() override {
JsEnv.Reset();
}
};
Method 2: Automatic binding mode
The advantage of this mode is that the class can be identified by the UE editor.
- Command line to enter
Plugins/Puerts
Directory, execute the following command to complete the opening and dependence installation of this mode
node enable_puerts_module.js
For example, such a class:
import * as UE from 'ue'
class TS_Player extends UE.Character {
}
export default TS_Player;
Then you can choose it in the UE editor.
- Can be identified by the UE, support constructor, support Override Blueprint Override method, support axial map Axis, Action event, support RPC
class TS_Player extends UE.Character {
FpsCamera: UE.CameraComponent;
//...
Constructor() {
let FpsCamera = this.CreateDefaultSubobjectGeneric<UE.CameraComponent>("FpsCamera", UE.CameraComponent.StaticClass());
FpsCamera.SetupAttachment(this.CapsuleComponent, "FpsCamera");
//...
}
MoveForward(axisValue: number): void {
this.AddMovementInput(this.GetActorForwardVector(), axisValue, false);
}
MoveRight(axisValue: number): void {
this.AddMovementInput(this.GetActorRightVector(), axisValue, false);
}
ReceiveBeginPlay(): void {
//...
}
//...
}
The relationship between two modes
- Automatic binding mode is based on the self-starting virtual machine mode,
PuertsModule
launches a virtual machine, then do some automatic binding blueprint, code increment compilation, incremental refresh feature - Both can be coexist, but you must keep in mind your own manually started virtual machine, and
PuertsModule
's virtual machine is not the same, they are isolated from each other.
Automatic binding mode
Format
A TypeScript satisfies three points below, a class can be identified by the UE editor
- This class inherits the class of the UE or the class of the other inheritance UE;
- The name of the file name and remove the
.ts
suffix; - Put this class export default。
Constructor
Unlike the standard TypeScript constructor
, the automatic binding mode is mainly written by the constructor of the UE initialization, that is, Constructor
class TsTestActor extends UE.Actor {
tickCount: number;
// Note that inheriting the JS class of the UE class, the constructor must be capitalized
Constructor() {
this.PrimaryActorTick.bCanEverTick = true;
tickCount = 0;
}
}
- Some UEs can be called in the constructor, such as
CreateDefaultSubobject
, which must be called in the constructor. - If a class defines a constructor, the initialization of the member variable will be taken over by TypeScript, then the value you set under the UE editor will be invalid.
- If the constructor is not defined, support to manually set member variables in the UE editor.
- Constructor is a constructor called by the UE, only as the initialization of the UE member.
- Can't do JS initialization work in this function, such as the initialization of variables for no-blueprint labels
- You cannot apply for JS resources in this function, such as creating a closure function, because these resources will fail after overloading the virtual machine, however the constructor will not re-execute
- Currently, it is not supported to modify the properties of the Component in an Actor, because
SpawnActor
has a reset to Component after constructing the object.: Constructor Settings component attribute is invalid
Automatic binding mode supported data type
Only the fields and methods supported by the type declared by the automatic binding mode can be identified by the UE
Type directly mapped
- void
- number
- string
- bigint
- boolean
- UObject derived class under the UE module
- enumerate
- UStruct
- TArray
- TSet
- TMap
- TSubclassOf (class reference)
- TSoftObjectPtr (soft object reference)
- TSoftClassPtr (soft class reference)
Note: A function return type declares that the void
is no return value. If a function does not declare the return type, it is equivalent to returning an any
type, and the automatic semi-butam mode does not support the any
type.
The following is a few fields and methods:
class TsTestActor extends UE.Actor {
tickCount: number;
actor: UE.Actor;
map: UE.TMap<string, number>;
arr: UE.TArray<UE.Object>;
set: UE.TSet<string>;
Add(a: number, b: number): number {
return a + b;
}
e: UE.ETickingGroup;
clsOfWidget: UE.TSubclassOf<UE.Widget>;
softObject: UE.TSoftObjectPtr<UE.Actor>;
softClass: UE.TSoftClassPtr<UE.Actor>;
}
Type annotation
Since Unreal has more fine-tuned types than TypeScript (i.e. TypeScript's number
represent's the same logical ideas as byte
, int
, float
, and double
that would be in UE), there needs to be supplemental annotations so Puerts can translate the types appropriately to C++. Here are some examples:
class TsTestActor extends UE.Actor {
//@cpp:text
Foo(): string {
return "hello";
}
Bar(p1:number/*@cpp:int*/): void {
}
//@cpp:name
Field: string;
}
Foo
return value isFText
Bar
's parameters areint
Field
is of typeFName
- Currently supported type annotations are:
text
name
int
byte
Other annotations
In addition to type annotations, Puerts also supports other annotations
@no-blueprint
indicates that a method or field is not available for UE blueprints to use
class TsTestActor extends UE.Actor {
//@no-blueprint
TsOnlyMethod():void {
}
//@no-blueprint
TsOnlyField: number;
}
rpc
You can set the RPC property of the method and fields with decorator.
Note: TypeScript decorators are not enabled by default; you need to set the experimentalDecorators
property to true
in tsconfig.json
rpc.flags
is used for setting flags for fields and methodsrpc.condition
is used to set the replication condition for fields
class TsTestActor extends UE.Actor {
@rpc.flags(rpc.PropertyFlags.CPF_Net | rpc.PropertyFlags.CPF_RepNotify)
@rpc.condition(rpc.ELifetimeCondition.COND_InitialOrOwner)
dint: number;
@rpc.flags(rpc.FunctionFlags.FUNC_Net | rpc.FunctionFlags.FUNC_NetClient)
Fire(): void {
}
@rpc.flags(rpc.FunctionFlags.FUNC_Net | rpc.FunctionFlags.FUNC_NetServer | rpc.FunctionFlags.FUNC_NetReliable)
FireServer(): void {
}
// If the field sets CPF_RepNotify, you need to add `OnRep_fieldname()` method.
OnRep_dint(): void {
}
}
Virtual machine switching
Puerts supports both V8
and quickjs
two virtual machines, and V8
currently has two versions.
- For UE 4.24 and below, the Android platform uses
V8
version7.4.288
, and other platforms version7.7.299
- For UE 4.25 and above, each platform can use
V8
version8.4.371.19
- For the size and demanding scenes,
quickjs
can be selected (Incanta here, I believe the translation here is meaning "if you want to reduce package size and need scalable performance" rather than "demanding")
The first V8
version provided by default.
If you want to use V8
version 8.4.371.19
, navigate to the V8 GitHub Actions and download the latest build V8
artifact. Extract the contents to Plugins/Puerts/ThirdParty
(or appropriate location). Then in the JsEnv.Build.cs
file, set UseNewV8
to true
.
If you want to use quickjs
, navigate to the quickjs GitHub Actions, download compiled quickjs
, extract to Plugins/Puerts/ThirdParty
(or appropriate location), and set UseQuickJs
to true
in the JsEnv.Build.cs
file.