Tencent/puerts项目中的蓝图Mixin技术详解
什么是蓝图Mixin
在Unreal Engine开发中,蓝图Mixin是一种强大的技术,它允许开发者将TypeScript类混合到现有的蓝图类中。通过Tencent/puerts项目提供的这一功能,开发者可以在保持原有蓝图结构的同时,用TypeScript代码增强或修改蓝图类的行为。
核心特性
1. 函数覆盖与增强
- 当TypeScript类与蓝图类拥有同名函数时,TypeScript逻辑会自动替换蓝图逻辑
- 支持覆盖Unreal Engine原生事件(如ReceiveBeginPlay等)
- 可以添加蓝图类中不存在的新方法和字段
2. 类型安全
- 系统会自动检查TypeScript函数与蓝图函数的兼容性
- 遵循TypeScript的协变逆变规则,确保类型安全
3. 性能优化
- TypeScript可以直接调用蓝图方法,并享有完整的代码提示
- 底层实现高效,不会引入不必要的性能开销
基础使用教程
1. 加载目标蓝图类
首先需要加载你想要混合的蓝图类:
let ucls = UE.Class.Load('/Game/StarterContent/MixinTest.MixinTest_C');
const MixinTest = blueprint.tojs<typeof UE.Game.StarterContent.MixinTest.MixinTest_C>(ucls);
2. 创建TypeScript混合类
定义一个TypeScript类来实现你想要混合的功能:
interface Loggable extends UE.Game.StarterContent.MixinTest.MixinTest_C {};
class Loggable {
// 覆盖蓝图中的同名函数
Log(msg: string): void {
console.log(this.GetName(), msg);
console.log(`1 + 3 = ${this.TsAdd(1, 3)}`);
}
// 新增TypeScript特有方法
TsAdd(x: number, y: number): number {
console.log(`Ts Add(${x}, ${y})`)
return x + y;
}
}
3. 执行混合操作
使用blueprint.mixin
方法将TypeScript类混合到蓝图类中:
const MixinTestWithMixin = blueprint.mixin(MixinTest, Loggable);
4. 使用混合后的类
现在可以像使用普通蓝图类一样使用混合后的类:
world.SpawnActor(MixinTestWithMixin.StaticClass(), undefined, UE.ESpawnActorCollisionHandlingMethod.Undefined, undefined, undefined) as Loggable;
高级应用场景
1. 对象生命周期管理
puerts提供了两种对象生命周期管理方式:
方式一:TypeScript持有UE对象(默认)
- TypeScript stub对象持有UE对象的强引用
- 当TypeScript对象不再被引用时,UE对象也会被释放
方式二:UE持有TypeScript对象
- UE对象持有TypeScript stub对象的强引用
- 当UE对象被销毁时,TypeScript对象也会被释放
可以通过blueprint.mixin
的第三个参数配置:
blueprint.mixin(MixinTest, Loggable, { objectTakeByNative: true });
2. 继承与super调用
当需要调用被覆盖的父类方法时,需要特殊处理:
// 创建中转类
interface MixinSuperTestBasePlaceHold extends UE.Game.StarterContent.MixinSuperTestBase.MixinSuperTestBase_C {};
class MixinSuperTestBasePlaceHold {}
Object.setPrototypeOf(MixinSuperTestBasePlaceHold.prototype, MixinSuperTestBase.prototype);
// 继承中转类
class DerivedClassMixin extends MixinSuperTestBasePlaceHold {
Foo(): void {
console.log("i am ts mixin");
super.Foo(); // 现在可以正确调用父类方法
}
}
3. 原生C++类的混合
puerts支持对C++原生类的BlueprintNativeEvent和BlueprintImplementableEvent方法进行混合:
class Calc {
Mult(x: number, y: number): number {
console.log(`Ts Mult(${x}, ${y})`)
return x * y;
}
Div(x: number, y: number): number {
console.log(`Ts Div(${x}, ${y})`)
return x / y;
}
}
interface Calc extends UE.MainObject {};
blueprint.mixin(UE.MainObject, Calc);
注意事项
-
事件覆盖:确保被混合的蓝图类中已经定义了你要覆盖的事件(即使逻辑为空),否则在子类中可能无法正确调用TypeScript逻辑。
-
新增字段:新增字段实际上是存储在TypeScript stub对象中:
- 当
objectTakeByNative
为false时,需要保持对stub对象的引用 - 当
objectTakeByNative
为true时,确保UE对象被引擎正确持有
- 当
-
性能考虑:虽然混合操作本身高效,但频繁的跨语言调用仍可能影响性能,建议将相关逻辑尽量集中处理。
通过Tencent/puerts的蓝图Mixin功能,开发者可以灵活地在TypeScript和蓝图之间架起桥梁,充分发挥两种开发方式的优势,提升开发效率和代码质量。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考