修复UE4的一个Cook稳定性bug
问题
最近在做热更补丁的时候遇到一个问题,就是保持资源不变的情况下,连续两次 Cook,部分资源的 Cook 结果不一致,具体体现在某个字节会随机地在 0x00 与 0x04 之间取值,如图
这个 Cook 不稳定的问题会导致做热更补丁包的时候,会将一些没有变化的资源文件也打进包中,导致冗余
分析
通过调试 Cook 序列化过程,最终定位到这个变化的字节是在序列化 FProperty
的 PropertyFlags
时候写入的,如图
也就是在连续两次 Cook 的时候,写入的 PropertyFlags
值不一致。对比两次写入的值 0x0000000400080004 和 0x0004000400080004,差异在 CPF_UObjectWrapper
这个标志位。
继续调试,发现这个标志位是在创建 FProperty
的时候根据 FEdGraphPinType
里的 bIsUObjectWrapper
的值来设置的,而 bIsUObjectWrapper
这个属性只在默认构造函数里进行了初始化,而其他的带参构造函数里都没有初始化,导致创建 FEdGraphPinType
对象的时候 bIsUObjectWrapper
会随机地取 true
或 false
,进而导致会随机地给 FProperty
对象随机设置 CPF_UObjectWrapper
标志位,然后序列化的时候就不一致了
修复
修复的方法很简单,就是在 FEdGraphPinType
类的所有构造函数和 ResetToDefaults
函数中正确初始化 bIsUObjectWrapper
后来在准备提交 PR 的时候发现官方已经在 4.27 中修复了这个问题,其他版本的还是需要自己修复一下,提交信息如图
调试 Cook Tips
- 调试具体资源的Cook时,如果项目大资源多,可以先通过 DirectoriesToNeverCook 配置将一些资源屏蔽
- 通过 -FullLoadAndSave 命令行将 Cook 过程的异步 Load/Save 转换成同步过程,方便调试
- 通过 -DIFFONLY 命令行可以调试前后两次 Cook 的差异信息