在游戏项目开发中,因为资源量大,涉及人员广,比较难自觉地统一资源规范,如果资源出现问题,手动排查要花费大量的人力,这也是资源管理的风险和痛点。
基于这种需求,我开发了一款编辑器下的资源扫描规范工具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
,可以在所有匹配规则检测的结果上进行取反,可以实现反向匹配的作用。
以Texture的命名规范为例:
提供了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*
这种后缀。
Editor中的检查提醒:
自定义规则
前面介绍了我提供的几种默认匹配规则,但是,如果有一些特殊的检测需求,我提供了一种方便的扩展方式,可以继承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仓库扫描配置:
在自定义规则蓝图中可以获取本地修改文件状态以及提交人:
执行扫描:
并且可以集成至Git GUI工具或者pre-commit hook中,实现完全自动化的检查:
2021.13.15 v24
- 修复从Git中获取map的提交信息失败
- 修复Mac上的Crash问题
- Commandlet扫描时关闭Shader的编译
优化安排
一些待优化思路,有时间会逐步实现。
实现属性名字的选择而不是输入Detail面板根据具体类型创建属性- 多线程规则检测,并行化处理