在游戏项目开发中,因为资源量大,涉及人员广,比较难自觉地统一资源规范,如果资源出现问题,手动排查要花费大量的人力,这也是资源管理的风险和痛点。
基于这种需求,我开发了一款编辑器下的资源扫描规范工具 ResScannerUE,可以非常方便地配置规则并实现自动化,由美术人员在资源提交前、定期执行等方式,提前检查项目中的资源是否合规,避免在打包后才发现问题。
本篇文章介绍 ResScannerUE 插件的使用方法、运行机制、自定义规则的扩展方式,以及后续的优化安排。
插件介绍
ResScannerUE 是一个基于 AssetRegistry 和反射机制实现的资源扫描工具,具有以下优点:
- 名字、路径规则检查无需加载资源
- 名字、路径规则提供通配符支持
- 可以通过提供属性名和值的方式检查资源中的选项
- 支持属性名、值的直接选择,避免输入
- 非常方便自定义拓展检查规则(创建蓝图或 C++ 类实现)
- 支持任意资源类型,绝大部分需求都能 Zero-Code 实现
- 支持配置的导入 / 导出
- 支持 Commandlet 实现自动化
- 支持 Git 提交的版本比对、待提交文件比对
- 支持的资源提交权限检查
命名、路径、属性可以严格匹配多个,也可以从多个规则中匹配一个,可以实现类似 (
(expression) && (expression || expression)
,如以T_
开头,以_x
或_d
等结尾这种模式的匹配)。
界面预览(与 HotPatcher 风格保持一致):
插件参数
FScannerConfig
- ConfigName:当前配置的名字
- bByGlobalScanFilters:开启所有 Rule 使用的全局扫描配置,开启后每个规则中的资源配置不生效
- bBlockRuleFilter:屏蔽每个规则中配置的资源,仅使用全局资源
- GlobalScanFilters:依赖
bByGlobalScanFilters
,所有 Rule 使用的全局扫描配置(会忽略每个 Rule 中指定的扫描配置) - GlobalIgnoreFilters:在所有规则中都忽略的资源(路径、某个资源)
- GitChecker:启用 GIT 版本检测
- bRuleWhiteList:开启规则白名单,只检测某些规则
- RuleWhileListIDs:白名单规则 ID 列表,注意:从 0 开始,RuleTable 里的 ID 要 - 1
- bUseRulesTable:是否启用规则数据表(建议)
- ImportRulesTable:指定一个 FScannerMatchRule 的 Datatable
- ScannerRules:
FScannerMatchRule
规则数组,用于指定资源检查规则 - bSaveConfig:是否保存配置文件
- bSaveResult:是否保存本次执行的结果
- SavePath:Config 和 Result 的存储路径
FGitChecker
能够提取 Git 检查提交版本中的文件进行检测:
- bGitCheck:启用 Git 仓库扫描
- bRecordCommiter:记录提交人
- RepoDir:GIT 仓库地址
- bDiffCommit:Git 提交记录比对(Begin/End Commit HASH)
- BeginCommitHash:检查开始的 Git Commit HASH
- EndCommitHash:检查结束的 Git Commit HASH
- bUncommitFiles:检查待提交文件
FScannerMatchRule
每个规则都支持以下参数:
- RuleName:规则名
- RuleDescribe:规则描述信息
- bEnableRule:是否启用当前规则
- Priority:该规则的优先级
- bGlobalAssetMustMatchFilter:必须匹配规则中的 Filter 目录 (全局资源),比如设置不同目录下的贴图规格不同,就要求只在某些目录下的资源才使用本规则扫描。
- ScanFilters:
FDirectoryPath
数组,指定扫描资源路径 - ScanAssetTypes:UClass 数组,指定要扫描的资源类型,建议每个规则只指定一个类型
- NameMatchRules:
FNameMatchRule
数组,用于指定命名匹配规则 - PathMatchRules:
FPathMatchRule
数组,用于指定资源的路径匹配规则 - PropertyMatchRules:
FPropertyMatchRule
数组,用于匹配资源中的属性 - CustomRules:
TSubclassOf<UOperatorBase>
数组,用于自定义匹配规则,可以指定 C++/ 蓝图类 - IgnoreFilters:本规则的忽略列表,(路径、某个资源)
- bEnablePostProcessor:是否开启对扫描结果的后处理
- PostProcessor:
TArray<TSubclassOf<UScannnerPostProcessorBase>>
数组,依赖 bEnablePostProcessor,可以指定对当前规则扫描的结果的后处理,如自动修改属性、自动重命名等等
FNameMatchRule
每一个 NameMatchRule 其中包含了多个 NameRule:
1 | USTRUCT(BlueprintType) |
FPathMatchRule
每一个 PathMatchRule 其中包含了多个 PathRule:
1 | USTRUCT(BlueprintType) |
FPropertyMatchRule
每个属性匹配规则,包含多个属性规则:
1 | USTRUCT(BlueprintType) |
匹配规则
我给 ResScannerUE 默认提供了四种种匹配方式:命名匹配、路径匹配、属性匹配、提交权限匹配、自定义匹配,可以实现大多数的资源扫描需求。
对于每种匹配方式,也可以添加了多个约束条件,以贴图命名规则为例:
- 贴图必须以
T_*
开头 - 根据贴图应用类型决定以
_c
或_d
结尾
其实就是需要由与或运算符组成两个限定条件:(T_) && ( _x || _d )
,在 ResScannerUE 的实现中,每个 NameRule,就是一个表达式,通过 MatchLogic
来决定内部是 and
/or
:
每个 NameRule 都具有一个 EMatchLogic
的属性,Necessary
是必须严格匹配所有的 Rule(T_
开头),Optional
是只需要对 Rule 中所有列出的匹配一个即可(_x
/_d
),路径和属性匹配也支持设置 MatchLogic
模式,同理。
命名匹配
对不同类型的资源制定命名规则是最常见的规范之一,如对 Texture,通常以 T_
开头。
在一个资源检测规则中,也可以添加多个路径匹配规则,每个匹配规则有三种模式:
- StartWith
- EndWith
- Wildcard
并且提供了 bReverseCheck
,可以在所有匹配规则检测的结果上进行取反,可以实现反向匹配的作用。
提供了 T_*
的通配符检查, 并且勾上了 bReverseCheck
,会记录不匹配这个规则的资源:
1 | { |
路径匹配
检查某种类型的资源是否按照指定的路径存储,也是最常用的规则之一。同样支持多种路径规范,每种规范默认支持两种模式:
- WithIn
- Wildcard
可以检查是否位于某一目录下,或者路径是否满足通配符规则。同样以 Texture 为例,检查 Texture 是否都被存储于命名为 */Textures/*
的目录中:
提供了 */Textures/*
的通配符检查, 并且勾上了 bReverseCheck
,会记录不匹配这个规则的资源:
1 | { |
属性匹配
检查某个资源中,是否启用了某个选项,或者检查某个属性的值,是资源合规检查中的重头。同样,对于资源属性检测也可以添加多个规则。
我基于反射实现了资源的属性匹配机制,对于任意资源类型,只要有反射标记的属性,都可以通过属性名和检测值来进行匹配,对于值的检测提供了两种模式:
- Equal
- NotEqual
如:CompressionSettings
被设置为 TC_Default
并且CompressionQuality
被设置为 TCQ_Highnest
或 TCQ_High
的贴图。
前面已经介绍了通过 MatchLogic
通过数组来实现逻辑处理的过程,在属性检测这里也格为重要。
能够检查出匹配的资源:
1 | { |
注意:属性匹配,是基于属性的反射名字进行检测,UE 里有(插件已支持选择属性)DisplayName
,在编辑器中显示的名字可能与真正的反射名字不一致,需要注意。
属性匹配,实现了基于反射的属性面板自定义,能够在选择 UClass 之后,自动列出所有的反射属性,并且根据所选择的属性名,自动在编辑器中创建出属性名的编辑器类型,非常的 Amazing:
提交权限匹配
支持对仓库中资源文件的修改权限检查,可以限定某种类型的资源只允许特定人员修改。比如,项目中的母材质只允许 TA 团队进行修改。
检测的两种模式:
- 基于 Git 内的提交信息
- 基于机器用户名
基于 Git 时,可以获取待提交文件、以及该文件最近一次提交记录的提交人。
基于机器用户名时,会获取当前机器的用户名,进行 StartsWith
检测,因为有些机器名会包含 lipengzha-PC*
这种后缀。
自定义规则
前面介绍了我提供的几种默认匹配规则,但是,如果有一些特殊的检测需求,我提供了一种方便的扩展方式,可以继承 UOperatorBase
类重载 Match
函数来实现自定义检测的需求。
1 | UCLASS(Blueprintable,BlueprintType) |
会传递当前资源的 UObject 以及字符串的 AssetType
,可以通过这两个数据进行自定义的检测。
在 Rule 的 CustomRules
中指定使用的类(TSubclassOf<UOperatorBase>
):
当然,也可以通过继承 UOperatorBase
创建蓝图类,一样实现重载,更方便:
当执行扫描的时候,会获取指定类的 CDO,调用 Match 函数,获取匹配结果。
如检测地图上 GameMode 的设置,这种需求就能通过自定义规则来实现:
如,提醒引用了 NerverCook 目录的资源,避免依赖的资源没进包造成的表现异常:
匹配后处理
插件提供了对匹配规则执行后处理的支持,如对不规范的资源属性进行自动化设置、自动重命名等需求。需要能够获取到匹配的结果。
我给每个 FScannerMatchRule
提供了一个指定 UScannnerPostProcessorBase
类的接口,如果想要对匹配规则的资源进行处理,可以继承 UScannnerPostProcessorBase
类实现 Processor
函数,会在当前规则扫描完毕之后将扫描结果传递过来。
1 | for(const auto& PostProcessorClass:Rule.PostProcessors) |
最终扫描结果
所有规则扫描完毕之后,结果是一个 FMatchedResult
结构,它包含了一个 FRuleMatchedInfo
数据,用于记录每个规则匹配的资源列表:
1 | // Rule Matched info |
RuleName
、RuleDescribe
、RuleID
可以比较方便地看出资源命中了哪条规则。
最终这个结构会被序列化为 Json 输出,如果想要获取原始的结果或者做一些特殊的处理,可以在 UResScannerProxy
调用 GetScanResult()
获取。
自动化检查
ResScannerUE 提供了 Commandlet 执行的方法,可以通过指定配置文件的方式启动:
1 | UE4Editor-cmd.exe PROJECT_NAME.uproject -run=ResScanner -config="res_scanner.json" |
可以添加 -wait
参数,在执行完毕之后等待输入,可以预览结果。
使用我之前开源的另一个工具 UELauncher 可以比较方便地实现配置:
基于 ResScannerUE 的自动化扫描实践,可以看我的另一篇文章:基于 ResScannerUE 的资源检查自动化实践
Update Log
2022.08.02 v25
- 支持检测 Git 待提交文件
- 支持扫描 TextureCube 规格
- 支持扫描地图 GameMode 设置
- 更深度的 Git 适配,支持检测某些资源只能某些用户修改
- 支持在规则中获取当前变动资源的修改人
- 支持插件中获取用户本地的 git 信息(username/email)
- 支持 commandlet 传递 gitusername
- 支持 pre-commit hook 的检查
以下案例需求:只允许某些用户才能够提交 Material 资源,其余用户拒绝提交。
新建一个过虑 Material 资源的规则,并指定一个自定义规则:
在自定义规则蓝图中可以获取本地修改文件状态以及提交人:
并且可以集成至 Git GUI 工具或者 pre-commit hook 中,实现完全自动化的检查:
2021.13.15 v24
- 修复从 Git 中获取 map 的提交信息失败
- 修复 Mac 上的 Crash 问题
- Commandlet 扫描时关闭 Shader 的编译
优化安排
一些待优化思路,有时间会逐步实现。
实现属性名字的选择而不是输入Detail 面板根据具体类型创建属性- 多线程规则检测,并行化处理
v1.4.14