BlueRoseNote/03-UnrealEngine/Gameplay/PuerTS/Puerts(一)——学习资料归纳.md

256 lines
9.1 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: Puerts——学习资料归纳
date: 2023-07-24 15:12:29
excerpt:
tags: Puerts TypeScript
rating: ⭐
---
# 前言
https://github.com/Tencent/puerts
- [安装方法](https://github.com/Tencent/puerts/blob/master/doc/unreal/zhcn/install.md)
- [FAQ](https://github.com/Tencent/puerts/blob/master/doc/unreal/zhcn/faq.md)
- [更新日志](https://github.com/Tencent/puerts/blob/master/doc/unreal/zhcn/changelog.md)
## Puerts
- 相关文章&视频:
- [UE引擎里头跑个nodejs服务器是怎样一种体验](https://zhuanlan.zhihu.com/p/428250631)
- [在你的ios、android应用中嵌入官方版nodejs是什么感觉](https://zhuanlan.zhihu.com/p/568969543)
- [[UnrealCircle深圳] puerts-UE下TypeScript编程插件 | 腾讯 车雄生](https://www.bilibili.com/video/BV1oB4y1A7dY/?spm_id_from=333.337.search-card.all.click&vd_source=d47c0bb42f9c72fd7d74562185cee290)
- 案例工程:
- https://github.com/chexiongsheng/puerts_unreal_demo
- 知乎文章:
- UE5 PuerTS学习与实践https://zhuanlan.zhihu.com/p/632862773
- UE4下基于V8实现的代码热刷新https://zhuanlan.zhihu.com/p/364505146
- PuerTSjs调用ue的过程https://zhuanlan.zhihu.com/p/396751427
- UE4PuerTS的js调试相关https://zhuanlan.zhihu.com/p/406387721
- 基于Puerts的编辑器UI开发-Mixin的非最佳实践https://zhuanlan.zhihu.com/p/551338775
## TypeScript
- http://www.patrickzhong.com/TypeScript/zh/tutorials/typescript-in-5-minutes.html
- https://ts.xcatliu.com/
- https://jkchao.github.io/typescript-book-chinese/#why
# TypeScript Setup
安装:
```bash
npm install -g typescript
```
编译:
```bash
tsc xxx.ts
```
# Puerts
## Setup
1. 编译插件。
2. 进入插件目录`Plugins\Puerts`执行`node enable_puerts_module.js`
3. 在项目根目录下执行`npm init`并且添加。之后重新生成一次VS解决方案并且执行`npm install`
```json
"dependencies": {
"@types/react": "^15.6.6",
"@types/react-reconciler": "^0.18.0",
"@types/mocha": "^7.0.1"
}
```
5. 代码写在项目目录下的`Content/TypeScript`中。
6. 之后就会在编辑器`Blueprints/TypeScript`目录下出现资产图标。
7. 加入ReactUMG。
1. 进入 Content/javascript 目录 npm init 创建 package.json。
2. 创建成功后,向文件中粘贴如下内容
```json
"dependencies": {
"react": "^16.11.0",
"react-reconciler": "^0.23.0"
}
```
3. 然后 npm install 一次。
4. 打开工程根目录的 tsconfig.json 在 typeRoots 中 加入 "Plugins/ReactUMG/Typing"。
8. 打开 工程,在引擎中点击 ue.d.ts 。
### Node环境设置
### 调试方法
具体可以参考:
- Puerts Inspector指南在UE4和Unity里调试Javascript:https://zhuanlan.zhihu.com/p/359598262
调试器的选择有:
1. 在Chrome输入`devtools://devtools/bundled/inspector.html?v8only=true&ws=127.0.0.1:8080`。
2. 在Chrome输入`chrome://inspect`点击Configure...输入IP&Port后点击Inspect。
3. 使用VSCode进行调试。
1. 在`Launch Program`处点击`add Configuration`。
2. 选择`Node.js: Attach`。
3. 设置端口。
4. 点击绿色箭头即可调试。
#### 方式1自创建虚拟机模式下调试配置
创建FJsEnv传入调试端口
```c++
//8080是调试端口 GameScript = MakeShared<puerts::FJsEnv>(std::make_unique<puerts::DefaultJSModuleLoader>(TEXT("JavaScript")), std::make_shared<puerts::FDefaultLogger>(), 8080);
```
阻塞等待调试器链接
```c++
GameScript = MakeShared<puerts::FJsEnv>(std::make_unique<puerts::DefaultJSModuleLoader>(TEXT("JavaScript")), std::make_shared<puerts::FDefaultLogger>(), 8080);
GameScript->WaitDebugger();
GameScript->Start("QuickStart", Arguments);
```
#### 方式2自动绑定模式下调试配置
1. 菜单上选择`Edit->ProjectSettings`,打开设置页面后在`Plugins -> Puerts Setting`页面中开启调试以及设置端口。
# TypeScript
- Express TypeScript化改造:https://www.jianshu.com/p/978628a15027
## Express
#### 使用ts-node将ts文件编译在内存中
在使用`ts-node`之前需要进行全局安装
```shell
$ npm install ts-node -g
# 用ts-node直接运行项目这个库会将我们的ts文件编译成js文件保存在内存中进行引用
$ ts-node ./bin/www
# 热更新模式
$ ts-node-dev ./bin/www
```
虽然`ts-node`可以帮我们直接运行ts文件但在开发完成后部署在生产环境时还是推荐使用`tsc`打包出来的`js`文件会更加稳定。
#### 配置npm脚本
```json
"scripts": {
"start": "ts-node app.ts",
"dev": "ts-node-dev app.ts",
"build": "tsc",
"server": "node ./dist/app.js"
},
```
# Puerts
Puerts的使用方法主要为
- 继承
- 继承原生UE C++类:继承并且实现之后就会在
- Mixin
- 在C++类中调用TypeScript文件
## puerts_unreal_demo 食用方法
项目默认使用UTsGameInstance可以在cpp中修改OnStart()中调用的TS脚本文件名来查看结果。优先查看TS文件
- QuickStart
- UsingMixin
- UsingMakeUClass
- UI
- UsingWidget
- UsingReactUMG
### 蓝图相关
```javascript
//蓝图加载
//UE.Class.Load方式
//let bpClass = UE.Class.Load('/Game/StarterContent/TestBlueprint.TestBlueprint_C')
//let bpActor = UE.GameplayStatics.BeginDeferredActorSpawnFromClass(gameInstance, bpClass, undefined) as UE.Game.StarterContent.TestBlueprint.TestBlueprint_C;
blueprint.load(UE.Game.StarterContent.TestBlueprint.TestBlueprint_C);
const TestBlueprint_C = UE.Game.StarterContent.TestBlueprint.TestBlueprint_C; //别名
let bpActor = UE.GameplayStatics.BeginDeferredActorSpawnFromClass(gameInstance, TestBlueprint_C.StaticClass(), undefined) as UE.Game.StarterContent.TestBlueprint.TestBlueprint_C;
UE.GameplayStatics.FinishSpawningActor(bpActor, undefined);
bpActor.Foo(false, 8000, 9000);
//如果确定后续不需要使用TestBlueprint_C了应该unload节省内存
blueprint.unload(TestBlueprint_C);
//蓝图结构体加载
//UE.UserDefinedStruct.Load方式
//let TestStruct = UE.UserDefinedStruct.Load("UserDefinedStruct'/Game/StarterContent/TestStruct.TestStruct'");
//let testStruct = UE.NewStruct(TestStruct) as UE.Game.StarterContent.TestStruct.TestStruct;
blueprint.load(UE.Game.StarterContent.TestStruct.TestStruct);
const TestStruct = UE.Game.StarterContent.TestStruct.TestStruct;
let testStruct = new TestStruct();
testStruct.age = 10;
testStruct.speed = 5;
bpActor.Bar(testStruct);
blueprint.unload(TestStruct);
//蓝图枚举
console.log("-------------------------15---------------------------");
console.log(UE.Game.StarterContent.TestEnum.TestEnum.Blue);
console.log(UE.Game.StarterContent.TestEnum.TestEnum.Red);
console.log(UE.Game.StarterContent.TestEnum.TestEnum.Green);
```
### Delegate
```javascript
//Delegate
function MutiCast1(i) {
    console.warn("MutiCast1<<<", i);
}
function MutiCast2(i) {
    console.warn("MutiCast2>>>", i);
    actor.NotifyWithInt.Remove(MutiCast2);//调用一次后就停掉
}
actor.NotifyWithInt.Add(MutiCast1)
actor.NotifyWithInt.Add(MutiCast2)
console.log("NotifyWithString.IsBound", actor.NotifyWithString.IsBound());
console.log("NotifyWithRefString.IsBound", actor.NotifyWithRefString.IsBound());
actor.NotifyWithRefString.Bind((strRef) => {
//console.error("NotifyWithRefString");
console.log("NotifyWithRefString", $unref(strRef));
$set(strRef, "out to NotifyWithRefString");//引用参数输出
});
console.log("NotifyWithString.IsBound", actor.NotifyWithString.IsBound());
console.log("NotifyWithRefString.IsBound", actor.NotifyWithRefString.IsBound());
actor.NotifyWithStringRet.Bind((inStr) => {
return "////" + inStr;
});
actor.NotifyWithInt.Broadcast(888999);
let strRef = $ref("666");
actor.NotifyWithRefString.Execute(strRef);
console.log("out str:" + $unref(strRef));
let retStr = actor.NotifyWithStringRet.Execute("console.log('hello world')");
console.log("ret str:" + retStr);
console.log("waiting native call script...........");
//Pass JsFunction as Delegate
function IsJohn(str:string) : boolean {
return str == "John";
}
obj.PassJsFunctionAsDelegate(toManualReleaseDelegate(IsJohn));
//release after using
releaseManualReleaseDelegate(IsJohn);
//unhandledRejection
on('unhandledRejection', function(reason: any) {
console.log('unhandledRejection~~~');
});
new Promise(()=>{
throw new Error('unhandled rejection');
});
```
## 热更新方法
https://zhuanlan.zhihu.com/p/364505146
## UE C++调用Puerts脚本方法
```c++
//h
TSharedPtr<puerts::FJsEnv> GameScript;
//cpp
GameScript = MakeShared<puerts::FJsEnv>();
TArray<TPair<FString, UObject*>> Arguments;
Arguments.Add(TPair<FString, UObject*>(TEXT("GameInstance"), this));
GameScript->Start("QuickStart", Arguments);
```
```javascript
//在FJsEnv启动调用Start时传入的参数可以通过argv获取。如果是继承ue类方式这里的argv是空的
let gameInstance = (argv.getByName("GameInstance") as UE.GameInstance);
let actor =  UE.GameplayStatics.BeginDeferredActorSpawnFromClass(gameInstance, UE.MainActor.StaticClass(), undefined) as UE.MainActor;
UE.GameplayStatics.FinishSpawningActor(actor, undefined);
console.log(actor.GetName());
console.log(actor.K2_GetActorLocation().ToString());
```
## UE C++访问Puerts
通过UDynamicDelegateProxy其成员记录了绑定的虚拟机与JS函数。