In game project development, due to the large amount of resources involved and the broad range of personnel, it’s relatively difficult to consciously unify resource standards. If issues arise with the resources, manually checking them requires a significant amount of manpower. This highlights the risks and pain points in resource management.
Based on this demand, I developed a resource scanning standard tool under the editor, ResScannerUE, which allows for easy configuration of rules and automation. This can be executed by artists before submitting resources or on a regular basis to check whether the resources in the project comply, thus avoiding issues that may only be discovered after packaging.
This article introduces the usage methods, operational mechanisms, ways to extend custom rules, and future optimization arrangements for the ResScannerUE plugin.
Plugin Introduction
ResScannerUE is a resource scanning tool implemented based on the AssetRegistry and reflection mechanism, with the following advantages:
- Name and path rule checks do not require loading of resources.
- Name and path rules provide support for wildcards.
- Options in resources can be checked by providing property names and values.
- Direct selection support for property names and values eliminates the need for input.
- Very convenient to customize and extend check rules (implementing with Blueprints or C++).
- Supports any resource type, most requirements can be implemented with Zero-Code.
- Supports import/export of configurations.
- Supports automation via Commandlet.
- Supports version comparison of Git commits and comparison of pending files.
- Supports resource submission permission checks.
Naming, path, and properties can strictly match multiple, or match one from multiple rules, enabling expressions like (
(expression) && (expression || expression)
, such as matching patterns that start withT_
and end with_x
or_d
).
Interface preview (maintaining consistency with the HotPatcher style):
Plugin Parameters
FScannerConfig
- ConfigName: The name of the current configuration.
- bByGlobalScanFilters: Enables the global scanning configuration used by all rules; when enabled, resource configurations in each rule do not take effect.
- bBlockRuleFilter: Shields resources configured in each rule, using only global resources.
- GlobalScanFilters: Depends on
bByGlobalScanFilters
, the global scanning configuration used by all rules (ignores scanning configurations specified in each rule). - GlobalIgnoreFilters: Resources ignored in all rules (paths, specific resources).
- GitChecker: Enables GIT version checking.
- bRuleWhiteList: Enables rule whitelist, checking only specific rules.
- RuleWhileListIDs: Whitelist rule ID list, Note: starts from 0, and IDs in RuleTable should be -1.
- bUseRulesTable: Whether to use a rules data table (recommended).
- ImportRulesTable: Specifies a Datatable of FScannerMatchRule.
- ScannerRules: Array of
FScannerMatchRule
rules for specifying resource check rules. - bSaveConfig: Whether to save the configuration file.
- bSaveResult: Whether to save the results of this execution.
- SavePath: Storage path for Config and Result.
FGitChecker
Able to extract files in Git commits for checking:
- bGitCheck: Enables Git repository scanning.
- bRecordCommiter: Records the committer.
- RepoDir: GIT repository address.
- bDiffCommit: Git commit record comparison (Begin/End Commit HASH).
- BeginCommitHash: The starting Git Commit HASH for checking.
- EndCommitHash: The ending Git Commit HASH for checking.
- bUncommitFiles: Checks pending files.
FScannerMatchRule
Each rule supports the following parameters:
- RuleName: Rule name.
- RuleDescribe: Rule description information.
- bEnableRule: Whether to enable the current rule.
- Priority: The priority of this rule.
- bGlobalAssetMustMatchFilter: Must match the Filter directory in the rule (global resource); for example, if different specifications for textures are set in different directories, only resources in certain directories should use this rule for scanning.
- ScanFilters: Array of
FDirectoryPath
, specifies scanning resource paths. - ScanAssetTypes: Array of UClass, specifies resource types to be scanned; it is recommended to specify only one type for each rule.
- NameMatchRules: Array of
FNameMatchRule
for specifying naming matching rules. - PathMatchRules: Array of
FPathMatchRule
for specifying resource path matching rules. - PropertyMatchRules: Array of
FPropertyMatchRule
for matching properties in resources. - CustomRules: Array of
TSubclassOf<UOperatorBase>
for custom matching rules; can specify C++/Blueprint classes. - IgnoreFilters: The ignore list for this rule (paths, specific resources).
- bEnablePostProcessor: Whether to enable post-processing of scan results.
- PostProcessor: Array of
TArray<TSubclassOf<UScannnerPostProcessorBase>>
, relies on bEnablePostProcessor; can specify post-processing of the current rule’s scan results, such as automatically modifying properties, auto-renaming, etc.
FNameMatchRule
Each NameMatchRule contains multiple NameRule:
1 | USTRUCT(BlueprintType) |
FPathMatchRule
Each PathMatchRule contains multiple PathRule:
1 | USTRUCT(BlueprintType) |
FPropertyMatchRule
Each property matching rule contains multiple property rules:
1 | USTRUCT(BlueprintType) |
Matching Rules
I provide four default matching methods for ResScannerUE: naming matching, path matching, property matching, submission permission matching, and custom matching, which can meet most resource scanning requirements.
For each matching method, multiple constraints can also be added. Taking the texture naming rule as an example:
- Textures must start with
T_*
. - Based on the application type of the texture, it should end with
_c
or_d
.
Essentially, two constraints composed of and/or operator need to be fulfilled: (T_) && (_x || _d)
. In the implementation of ResScannerUE, each NameRule is an expression that determines if the internal logic is and
/or
by MatchLogic
.
Each NameRule has an attribute of EMatchLogic
. Necessary
must strictly match all Rules (starting with T_
), whereas Optional
means only one of the patterns listed in the Rule needs to match (_x
/_d
). Path and property matching also supports setting the MatchLogic
mode similarly.
Naming Matching
Setting naming rules for different types of resources is one of the most common standards, such as textures usually starting with T_
.
In a resource detection rule, multiple path matching rules can also be added, with each matching rule having three modes:
- StartWith
- EndWith
- Wildcard
Additionally, bReverseCheck
is provided to negate the results of all matching rules for reverse matching.
Taking the naming standard for textures as an example:
It includes a wildcard check of T_*
, and enabling bReverseCheck
will record resources that do not match this rule:
1 | { |
Path Matching
Checking whether a certain type of resource is stored according to a specified path is also one of the most common rules. It similarly supports multiple path specifications, and each specification default supports two modes:
- WithIn
- Wildcard
It can check whether the resource is located within a certain directory or whether the path meets the wildcard criteria. Taking textures again as an example, one could check whether all textures are stored in directories named */Textures/*
:
It includes a wildcard check for */Textures/*
and enabling bReverseCheck
will record resources that do not match this rule:
1 | { |
Property Matching
Checking whether a certain option is enabled within a resource or checking the value of a specific property is a key aspect of resource compliance checking. Similarly, multiple rules can be added for property attribute detection.
I have implemented a mechanism for property matching based on reflection, wherein any resource type can be checked as long as it has reflection-marked properties. Property matching can be done through property names and detection values, with two modes for value checking:
- Equal
- NotEqual
For example, checking if CompressionSettings
is set to TC_Default
and CompressionQuality
is set to either TCQ_Highnest
or TCQ_High
for textures. I have previously described how the MatchLogic
array can be used to handle the logical processing. This is also important for property detection.
Successfully matching resources can be retrieved:
1 | { |
Note: Property matching is based on the reflection name of the property; in UE there is(The plugin now supports property selection)DisplayName
, which may not match the actual reflection name shown in the editor, so care should be taken.
Property matching allows for custom reflection-based property panels, capable of automatically listing all reflected properties after selecting UClass, and automatically creating property name editor types in the editor based on the selected property name, which is very amazing:
Submission Permission Matching
Supports checking modification permissions of resource files in the repository, allowing only specific personnel to modify certain types of resources. For example, certain master materials in the project may only be modified by the TA team.
There are two modes of checks:
- Based on the commit information in Git.
- Based on machine username.
When based on Git, pending files can be retrieved, along with the most recent submitter of the file:
When based on machine usernames, the current machine’s username is retrieved, and a StartsWith
check is performed since some machine names may include suffixes like lipengzha-PC*
.
Editor displays alerts on checks:
Custom Rules
While I have introduced several default matching rules, for some special detection needs, I offer a convenient extension method where subclasses can inherit from UOperatorBase
and override the Match
function to implement custom detection needs.
1 | UCLASS(Blueprintable,BlueprintType) |
This will pass the current resource’s UObject and the AssetType
string, allowing for customized detection based on this data.
In the Rule’s CustomRules
, specify the class to be used (TSubclassOf<UOperatorBase>
):
Alternatively, one can also create Blueprint classes by inheriting UOperatorBase
, making it even easier to implement overrides:
When executing a scan, the specified class’s CDO will be obtained, and the Match function will be called to get the matching results.
For example, detecting settings of GameMode on a map can be achieved through a custom rule:
Another example, alerting when resources reference the NeverCook directory to avoid issues caused by missing dependencies during packaging:
Post-Processing After Matching
The plugin provides support for performing post-processing on matching rules, such as automated setting of non-compliant resource properties or auto-renaming needs. It is essential to be able to access matching results.
I provide an interface in each FScannerMatchRule
for specifying a UScannnerPostProcessorBase
class. If one intends to process resources that match the rules, they can inherit the UScannnerPostProcessorBase
class and implement the Processor
function. This will pass the scan results to it after the current rule’s scan is complete.
1 | for(const auto& PostProcessorClass:Rule.PostProcessors) |
Final Scan Results
Once all rule scans are completed, the results are structured in an FMatchedResult
, containing a FRuleMatchedInfo
for recording the list of resources matched by each rule:
1 | // Rule Matched info |
RuleName
, RuleDescribe
, and RuleID
provide a convenient way to determine which rules the resources matched against.
Ultimately, this structure will be serialized into JSON output. If you want to obtain the original results or perform some special processing, you can call GetScanResult()
in UResScannerProxy
.
Automated Checks
ResScannerUE offers methods for executing via Commandlet, initiated by specifying the configuration file:
1 | UE4Editor-cmd.exe PROJECT_NAME.uproject -run=ResScanner -config="res_scanner.json" |
One can add the -wait
parameter to wait for input after execution completes, allowing for previewing results.
Utilizing another previously open-sourced tool, UELauncher, can facilitate configuration:
For practical automated scanning implementations based on ResScannerUE, refer to my other article: Automated Practices for Resource Checks Based on ResScannerUE
Update Log
2022.08.02 v25
- Support for checking Git pending files.
- Support for scanning TextureCube specifications.
- Support for scanning GameMode settings in maps.
- Deepened Git adaptation, supporting checks that certain resources can only be modified by specific users.
- Support for retrieving the modifier of currently changing resources in rules.
- Support for getting user local git information (username/email) in the plugin.
- Support for passing git username via commandlet.
- Support for checking pre-commit hooks.
For the following case requirement: only specific users can submit Material resources, while others are denied submission.
A rule filtering Material resources was created and a custom rule specified:
In the scanning configuration, enable global resources and Git repository scanning configurations:
In the custom rule blueprint, obtain the status of locally modified files and the committer:
Execute the scan:
Additionally, it can be integrated into Git GUI tools or pre-commit hooks to achieve fully automated checks:
2021.13.15 v24
- Fixed failure to retrieve commit information for maps from Git.
- Fixed crash issues on Mac.
- Disabled shader compilation during commandlet scanning.
Optimization Plans
Some thoughts for future optimizations; I will gradually implement these when time permits.
Implement property name selection instead of input.Create property based on specific types in the Detail panel.- Multi-threaded rule detection for parallel processing.