Udon Decompiler

提取 UdonModuleInfo.json

Udon VM - 执行过程Udon VM - 外部函数中解释了 Udon VM 如何调用外部函数. 为了正常识别外部函数调用, 并重建更高级的语义信息, 本反编译器也需要知道每个 externSignatureexternSignature 所对应函数的参数数量, 原始名字, 具体类型(methodmethod, ctorctor, opop, fieldfield), 是否有返回值, 是否为静态函数等信息.

这一提取工作通过编辑器脚本 UdonModuleInfoExtractor.csUdonModuleInfoExtractor.cs 完成, 其大致运行逻辑如下

  • 使用 UdonVMUdonVM 所使用的 API 获取所有实现了 IUdonWrapperModuleIUdonWrapperModule 的类
  • 对于每一个类, 读取它们的 NameName(externSignatureexternSignature 中的 ModuleNameModuleName) 和 _parameterCounts_parameterCounts(Dictionary<string, int>Dictionary<string, int>) 字段. 从而获得每个 externSignatureexternSignature 对应的参数数量
  • 使用 NodeRegistriesNodeRegistries 相关 API 获取每个 externSignatureexternSignature 对应的 UdonNodeDefinitionUdonNodeDefinition
  • 对于每个类中的每个函数, 使用其函数签名和 UdonNodeDefinitionUdonNodeDefinition 中的参数列表信息推断我们需要的所有信息, 具体而言

    • 推断类的原始名字: 使用该类中任一函数的 UdonNodeDefinition.typeUdonNodeDefinition.type 即可获得该类的 TypeType
    • 推断类型: 根据函数签名的开头和参数数量的不同

      • __op___op_ 开头的, 是 opop 类型
      • __ctor____ctor__ 开头的, 是 ctorctor 类型
      • __get___get___set___set_ 开头的且参数数量不小于 1, 不大于 2 的, 是 fieldfield 类型(签名符合特征但是参数数量不正确的那部分函数是数组成员访问. 截至目前, 这种类型的函数还没有被正确反编译, 相关工作在 todo 列表中)
      • 其它的是 methodmethod 类型
    • 推断原始名字

      • 对于 fieldfield 类型: 将函数签名去掉开头的 __get___get___set___set_ 即为原始名字
      • 对于 methodmethod 类型: 将对应 UdonNodeDefinition.nameUdonNodeDefinition.name 用空格 rsplitrsplit, 最后一段即为原始名字
    • 推断是否为静态函数: 检查 UdonNodeDefinition.parameters.First()UdonNodeDefinition.parameters.First()namename 是否为 instanceinstance 且类型是否与该类相同
    • 推断是否有返回值: 检查 UdonNodeDefinition.parameters.Last()UdonNodeDefinition.parameters.Last()parameterTypeparameterType 是否为 UdonNodeParameter.ParameterType.OUTUdonNodeParameter.ParameterType.OUT
  • 将所有信息输出到 UdonModuleInfo.jsonUdonModuleInfo.json