Puerts插件开发指南:自定义TypeScript绑定生成器实现

Puerts插件开发指南:自定义TypeScript绑定生成器实现

【免费下载链接】puerts PUER(普洱) Typescript. Let's write your game in UE or Unity with TypeScript. 【免费下载链接】puerts 项目地址: https://gitcode.com/GitHub_Trending/pu/puerts

你是否还在为手动编写TypeScript绑定代码而烦恼?是否希望有更灵活的方式来控制UE或Unity项目中的TypeScript类型定义生成?本文将带你从零开始实现一个自定义TypeScript绑定生成器,让TypeScript与原生代码的交互变得更加高效可控。

读完本文后,你将能够:

  • 理解Puerts绑定生成器的工作原理
  • 配置自定义的类型绑定规则
  • 实现函数过滤与属性扩展
  • 优化生成的TypeScript声明文件

绑定生成器基础原理

Puerts通过静态绑定生成(StaticWrapper)技术,将C#/C++接口转换为TypeScript可调用的格式,避免了运行时反射带来的性能开销。默认情况下,Puerts会根据预设规则生成绑定代码,但在实际开发中,我们常常需要根据项目需求自定义生成逻辑。

TypeScript绑定生成流程

绑定生成器的核心工作流程包括:

  1. 扫描指定的C#/C++类型
  2. 根据配置规则过滤和转换
  3. 生成静态调用包装类(StaticWrapper)
  4. 输出TypeScript声明文件(.d.ts)

相关实现代码位于unreal/Puerts/Source/DeclarationGenerator/目录,该模块负责解析原生类型并生成对应的TypeScript定义。

配置基础:绑定规则定义

所有绑定配置类都需要放置在Editor目录下,并使用[Configure]标签标记。最基础的配置包括指定需要绑定的类型列表,这通过[Binding]属性实现。

[Configure]
public class GameplayCfg
{
    [Binding]
    static IEnumerable<Type> Bindings
    {
        get
        {
            return new List<Type>()
            {
                typeof(UnityEngine.GameObject),
                typeof(UnityEngine.Transform),
                typeof(MyGame.PlayerController)
            };
        }
    }
}

上述代码会生成GameObject、Transform和自定义PlayerController的TypeScript绑定。完整的配置标签说明可参考doc/unity/zhcn/wrapper/all_attribute.md

动态类型收集

对于大型项目,手动维护类型列表效率低下,可通过反射动态收集类型:

[Binding]
static IEnumerable<Type> Bindings
{
    get
    {
        return Assembly.Load("Assembly-CSharp")
            .GetTypes()
            .Where(t => t.Namespace.StartsWith("MyGame") && 
                       t.GetCustomAttributes(typeof(ExportAttribute), false).Length > 0);
    }
}

这种方式会自动收集所有标记了[Export]属性的自定义类型,极大减少了配置维护成本。

高级过滤:函数与属性定制

成员过滤

使用[Filter]标签可以精确控制哪些成员需要生成绑定。例如,我们可能希望隐藏某些内部方法:

[Filter]
static bool Filter(MemberInfo memberInfo)
{
    // 排除以"Internal"开头的方法
    if (memberInfo is MethodInfo method && method.Name.StartsWith("Internal"))
        return false;
        
    // 排除Editor专用属性
    if (memberInfo is PropertyInfo prop && prop.Name == "EditorOnlyData")
        return false;
        
    return true;
}

详细的过滤规则配置可参考doc/unity/zhcn/wrapper/filter.md

blittable类型优化

对于Vector3等 blittable 类型(内存布局连续的值类型),可启用内存拷贝优化,大幅减少GC开销:

[BlittableCopy]
static IEnumerable<Type> Blittables
{
    get
    {
        return new List<Type>()
        {
            typeof(Vector3),
            typeof(Quaternion),
            typeof(Color)
        };
    }
}

启用此特性需要在项目中开启unsafe编译选项,具体配置方法见doc/unity/zhcn/wrapper/blittablecopy.md

自定义TypeScript类型生成

类型名称映射

当原生类型名称与TypeScript习惯用法冲突时(如C#中的object类型),可通过扩展生成器实现名称映射。创建自定义生成器需要继承Puerts的ICustomCodeGenerator接口:

class TypeNameMapper implements ICustomCodeGenerator {
    GenerateCode(type: TypeInfo): string {
        // 将C#的"Object"映射为TypeScript的"any"
        if (type.Name === "Object" && type.Namespace === "System") {
            return "any";
        }
        // 保留默认生成逻辑
        return null;
    }
}

方法签名转换

对于重载方法,TypeScript不支持参数类型重载,需要生成不同名称的函数。可通过自定义生成器实现自动重命名:

class MethodOverloadHandler implements ICustomCodeGenerator {
    GenerateCode(method: MethodInfo): string {
        if (method.Overloads.Length > 1) {
            // 为每个重载生成带参数类型后缀的方法名
            const paramTypes = method.Parameters.map(p => p.Type.Name);
            return `${method.Name}_${paramTypes.join('_')}`;
        }
        return null;
    }
}

生成流程与调试

触发生成

在Unity中,通过菜单Tools/PuerTS/Generate Code手动触发生成;在UE中,可通过执行GenerateTypeScriptDeclarations命令。生成的TypeScript声明文件默认输出到项目的Content/Scripts目录。

调试技巧

  1. 开启生成日志:在配置类中添加[LogLevel(LogLevel.Debug)]查看详细生成过程
  2. 检查临时文件:生成器会在Temp目录保留中间处理结果
  3. 使用[Typing]标签:仅生成TypeScript声明而不生成静态包装,加快调试迭代
[Typing]
static IEnumerable<Type> Typings
{
    get { return new List<Type> { typeof(MyDebugType) }; }
}

实战案例:网络模块绑定优化

假设我们有一个网络模块,需要将C#的网络消息类型转换为TypeScript接口,并自动添加序列化逻辑。

自定义属性标记

[AttributeUsage(AttributeTargets.Class)]
public class NetworkMessageAttribute : Attribute { }

[NetworkMessage]
public class LoginRequest
{
    public string Username;
    public string PasswordHash;
}

自定义生成器实现

class NetworkMessageGenerator implements ICustomCodeGenerator {
    GenerateCode(type: TypeInfo): string {
        if (!type.HasAttribute("NetworkMessage")) return null;
        
        // 生成TypeScript接口
        let code = `export interface ${type.Name} {\n`;
        
        // 添加字段定义
        type.Fields.forEach(field => {
            code += `    ${field.Name}: ${ConvertType(field.Type)};\n`;
        });
        
        // 添加序列化方法
        code += `\n    toBytes(): Uint8Array {\n`;
        code += `        const buffer = new ArrayBuffer(${CalculateSize(type)});\n`;
        code += `        const view = new DataView(buffer);\n`;
        // 字段序列化逻辑...
        code += `        return new Uint8Array(buffer);\n    }\n}`;
        
        return code;
    }
}

通过这种方式,我们实现了网络消息类型的自动转换与序列化代码生成,大幅减少了手动编写的工作量。

总结与扩展方向

自定义TypeScript绑定生成器是提升Puerts项目开发效率的关键技术。通过本文介绍的配置方法,你可以实现:

  • 根据项目需求定制类型绑定规则
  • 优化生成代码的性能与体积
  • 自动生成重复性代码(如序列化、事件分发)
  • 统一团队的代码规范与接口设计

未来可以进一步探索的方向:

  • 实现基于注释的文档自动生成
  • 添加类型验证与错误检查
  • 开发可视化配置工具

希望本文能帮助你更好地掌握Puerts的高级用法,让TypeScript与游戏引擎的交互更加顺畅高效。如有任何问题,可参考官方文档doc/unity/zhcn/wrapper/wrapper.md或加入社区讨论获取支持。

记得点赞收藏本文,关注后续关于Puerts性能优化的进阶教程!

【免费下载链接】puerts PUER(普洱) Typescript. Let's write your game in UE or Unity with TypeScript. 【免费下载链接】puerts 项目地址: https://gitcode.com/GitHub_Trending/pu/puerts

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值