-
在合适的地方(比如GameInstance)根据需要启动一个或者多个虚拟机
- 如果启动多个虚拟机,这些虚拟机间是相互隔离的
-
通过Start函数启动一个脚本,作为脚本逻辑的入口(类似c的main函数)
- Start可以传入一些数据作为参数,供脚本获取使用
-
在虚拟机里头的脚本可以按puerts的规则(后面的章节)和引擎交互
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();
}
};
该模式的优点是能做到特定写法的类能被UE编辑器识别
- 命令行进入Plugins/Puerts目录,执行如下命令即可完成该模式的开启和依赖安装
node enable_puerts_module.js
例如这么一个类:
import * as UE from 'ue'
class TS_Player extends UE.Character {
}
export default TS_Player;
然后你在UE编辑器就能选择它
- 能被UE识别的类,支持构造函数,支持override蓝图能override的方法,支持轴映射Axis、Action事件,支持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 {
//...
}
-
自动绑定模式是建立于自行启动虚拟机模式的基础上的,PuertsModule启动了一个虚拟机,然后做了些自动绑定蓝图,代码增量编译、增量刷新功能
-
两者可以并存,但要谨记你自己手动启动的虚拟机,和PuertsModule的虚拟机不是同一个,他们是相互隔离的
一个TypeScript满足如下以下三点,一个类才能被UE编辑器识别
- 这个类继承自UE的类或者另一继承UE的类;
- 类名和去掉.ts后缀的文件名相同;
- 把这个类export default。
和标准的typescript构造函数不一样,自动绑定模式被UE初始化调用的构造函数首字母需大写,也就是Constructor
class TsTestActor extends UE.Actor {
tickCount: number;
//注意,继承UE类的js类,构造函数必须大写开头
Constructor() {
this.PrimaryActorTick.bCanEverTick = true;
tickCount = 0;
}
}
- 构造函数中可以调用一些UE限定必须在构造函数调用的API,比如CreateDefaultSubobject
- 如果一个类定义了构造函数,该类成员变量的初始化会被TypeScript接管,这时你在UE编辑器下设置的值将会无效
- 如果没定义构造函数,则支持在UE编辑器手动设置成员变量值
- Constructor是UE调用的构造函数,不能在该函数中做js的初始化工作,比如no-blueprint标注的变量的初始化
只有用自动绑定模式支持的类型声明的字段、方法,才能被UE识别
直接映射的类型
void,number,string,bigint,boolean,UE模块下的UObject派生类、枚举、UStruct,TArray、TSet、TMap、TSubclassOf(类引用)、TSoftObjectPtr(软对象引用)、TSoftClassPtr(软类引用)
注意:一个函数返回类型声明为void才是无返回值,如果一个函数不声明返回类型,等同于返回any类型,而自动半丁模式并不支持any类型
如下是几个字段和方法的示例:
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>;
}
类型注解
TypeScript和UE两者间的数据类型丰富程度不一样,因而两者并不是一一映射的,比如UE里头的byte,int,float都对应TypeScript的number,那么我们如何告诉puerts生成我们所需的类型呢?puerts提供了类型注解,如下是几个例子:
class TsTestActor extends UE.Actor {
//@cpp:text
Foo(): string {
return "hello";
}
Bar(p1:number/*@cpp:int*/): void {
}
//@cpp:name
Field: string;
}
- Foo的返回值是FText
- Bar的参数是int
- Field字段的类型是FName
- 目前支持的类型注解支持的类型有:text,name,int,byte
除了类型注解,puerts还支持其它注解
- @no-blueprint
表示不被UE编辑器识别,方法和字段均可用
class TsTestActor extends UE.Actor {
//@no-blueprint
TsOnlyMethod():void {
}
//@no-blueprint
TsOnlyField: number;
}
可以通过decorator来设置方法、字段的RPC属性。
注意:TypeScript的decorator默认不打开,需要在tsconfig.json上将experimentalDecorators属性设置为true
- rpc.flags
为字段,方法设置flags
- rpc.condition
为字段设置replicate condition
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 {
}
//如果字段设置了CPF_RepNotify,需要增加“OnRep_字段名”为名字的方法
OnRep_dint(): void {
}
}
puerts同时支持V8和quickjs两种虚拟机,而V8目前有两套版本
- 对于UE4.24及以下,android用的是7.4.288版本的v8,其它系统用的是7.7.299版本的v8
- 对于高于4.24的版本,可以各操作性统一为8.4.371.19
- 对于包大小苛刻的场景,可以选用quickjs
默认提供的上述第一种V8版本。
希望使用8.4.371.19的v8的话,先到这里下载编译好的V8,解压到Plugins/Puerts/ThirdParty下,然后把JsEnv.Build.cs的UseNewV8修改为true
希望使用quickjs的话,先到这里下载编译好的quickjs,解压到Plugins/Puerts/ThirdParty下,然后把JsEnv.Build.cs的UseQuickjs修改为true