역자의 말 : 텐센트에서 근무하는 엔지니어 lipengzha의 예전 포스트를 번역해 봤습니다. 모 회사 컨설팅 과정에서 너무 바쁘고 일손이 부족해 미흡했던 데이터 검증 부분을 새롭게 구성하기 위한 사전 조사입니다.
게임 개발 초반에는 테크아트 부서에서도 크게 신경 쓰지 않거나 우선순위가 뒤로 밀리는 부분이라 많이 아쉬웠습니다. 시간이 지나 서비스 단계나 QA 빌드에 가까워질수록, 클라이언트 코드 버그만큼이나 많은 데이터 오류가 일정을 갉아먹는 필드보스급 범인이었기 때문입니다.
데브옵스팀이 있던 회사에서 최근 10년간 근무했을 때는 그분들이 워낙 잘해주셔서 "내 일이 아니다"라고 생각했습니다. 하지만 데브옵스팀이 없는 스타트업에서는 정말 큰 문제였고, 최근에는 예전보다 더 중요한 부분이라고 생각하게 됐습니다.
특히 스타트업의 경우 창업 멤버의 시니어 레벨에 비해 경험이 적은 분들이 더 많은 비중을 차지합니다. 따라서 데이터 검증 자동화를 초반에 잘 갖추는 것이 회사의 잠재적 기회비용을 올바른 곳에 사용할 수 있도록 하는 길입니다.
Personal Insight : CG 업체 컨설팅을 할 때 그리고 오래 전에 CG 회사에 잠깐 근무 할 때 느낀점은 테크아트 부문에서 Data Validation 에 꽤나 많은 시간과 노력을 투자했던 것 같아요. 지금 생각해 보면 산업 환경 때문인것 같습니다. 보통 CG 회사들은 시간이 곧 수익률 입니다. 그래서 렌더링 단계에서 모델 데이터나 리그 데이터등에 문제가 있어 다시 렌더링 해야 하거나 렌더링이 실패 하거나 하면 그대로 바로 수익률이 하락하는 게 됩니다. 그리고 여러 툴 간의 Cross Work 이 워낙 많았기 때문일 수도 있는 것 같습니다. 반대로 국내 게임회사를 보면 시간이 돈이라는 개념이 좀 약한 부분이 있는것 같습니다. 출시일정은 신경 쓰지만 어떻게 출시일정을 맞출 것인지 세부적인 계획을 마일스톤 정도로 끝내는 게 아닌가… PM 이 그냥 스케줄링하고 조율 하고 협상하는 시스템 같다는 느낌이 드네요. 오늘 됬는데 커밋 하고 보면 정작 애러가 나오고 그럼 또 이틀이 지나가고 이게 1년씩 2년씩 3년 씩 계속 반복되어도 부서간의 협상이 없고 좋게 좋게 그냥 넘어가는 것이 아닌가 약간 그런 생각이 들었습니다. 많은 국내 회사를 다녀본 적이 없기 때문에 인사이트 자체가 보편성을 갖지 못하지만 스타트업의 경우 프러덕트 오너의 경험에 따라 마일스톤 핸들링을 어떻게 하는지가 결정 되는 경향이 있지만 이런 부분은 해외 개발사처럼 딱딱해 보이지만 분명한 룰이 있어야 하고 시스템이 있어야 하는 것 같습니다.
게임 프로젝트 개발에서는 리소스 양이 방대하고 관련 인원이 많아 리소스 규범을 자발적으로 통일하기 어렵습니다. 리소스에 문제가 발생하면 수동으로 검사하는 데 많은 인력이 소요되며, 이는 리소스 관리의 위험 요소이자 문제점입니다.
이러한 필요에 따라 저는 에디터 기반의 리소스 스캔 규범 도구인 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이 포함됩니다:
USTRUCT(BlueprintType)
structFNameRule
{
GENERATED_USTRUCT_BODY()
public:
UPROPERTY(EditAnywhere,BlueprintReadWrite)
ENameMatchMode MatchMode;
// 매칭 규칙, 필수인지 선택인지, Necessary는 모든 규칙을 반드시 매칭, Optional은 규칙 중 하나만 매칭하면 됨
UPROPERTY(EditAnywhere,BlueprintReadWrite)
EMatchLogic MatchLogic;
// UPROPERTY(EditAnywhere,BlueprintReadWrite,meta=(EditCondition="MatchLogic == EMatchLogic::Optional"))
int32 OptionalRuleMatchNum =1;
UPROPERTY(EditAnywhere,BlueprintReadWrite)
TArray<FString> Rules;
};
USTRUCT(BlueprintType)
structFNameMatchRule
{
GENERATED_USTRUCT_BODY()
public:
UPROPERTY(EditAnywhere,BlueprintReadWrite)
TArray<FNameRule> Rules;
UPROPERTY(EditAnywhere,BlueprintReadWrite)
bool bReverseCheck;
};
FPathMatchRule
각 PathMatchRule에는 여러 PathRule이 포함됩니다:
USTRUCT(BlueprintType)
structFPathRule
{
GENERATED_USTRUCT_BODY()
public:
UPROPERTY(EditAnywhere,BlueprintReadWrite)
EPathMatchMode MatchMode;
// 매칭 규칙, 필수인지 선택인지, Necessary는 모든 규칙을 반드시 매칭, Optional은 규칙 중 하나만 매칭하면 됨
UPROPERTY(EditAnywhere,BlueprintReadWrite)
EMatchLogic MatchLogic;
// UPROPERTY(EditAnywhere,BlueprintReadWrite,meta=(EditCondition="MatchLogic == EMatchLogic::Optional"))
int32 OptionalRuleMatchNum =1;
UPROPERTY(EditAnywhere,BlueprintReadWrite,meta = (RelativeToGameContentDir, LongPackageName))
TArray<FString> Rules;
};
USTRUCT(BlueprintType)
structFPathMatchRule
{
GENERATED_USTRUCT_BODY()
public:
UPROPERTY(EditAnywhere,BlueprintReadWrite)
TArray<FPathRule> Rules;
UPROPERTY(EditAnywhere,BlueprintReadWrite)
bool bReverseCheck;
};
FPropertyMatchRule
각 속성 매칭 규칙에는 여러 속성 규칙이 포함됩니다:
USTRUCT(BlueprintType)
structFPropertyRule
{
GENERATED_USTRUCT_BODY()
public:
// 매칭 규칙, 필수인지 선택인지, Necessary는 모든 규칙을 반드시 매칭, Optional은 규칙 중 하나만 매칭하면 됨
UPROPERTY(EditAnywhere,BlueprintReadWrite)
EMatchLogic MatchLogic;
// UPROPERTY(EditAnywhere,BlueprintReadWrite,meta=(EditCondition="MatchLogic == EMatchLogic::Optional"))
int32 OptionalRuleMatchNum =1;
UPROPERTY(EditAnywhere,BlueprintReadWrite)
TArray<FPropertyMatchMapping> Rules;
};
USTRUCT(BlueprintType)
structFPropertyMatchRule
{
GENERATED_USTRUCT_BODY()
public:
UPROPERTY(EditAnywhere,BlueprintReadWrite)
TArray<FPropertyRule> Rules;
UPROPERTY(EditAnywhere,BlueprintReadWrite)
bool bReverseCheck;
};
매칭 규칙
ResScannerUE에 기본적으로 네 가지 매칭 방식을 제공합니다: 이름 매칭, 경로 매칭, 속성 매칭, 제출 권한 매칭, 사용자 정의 매칭으로, 대부분의 리소스 스캔 요구사항을 구현할 수 있습니다.
각 매칭 방식에 대해 여러 제약 조건을 추가할 수 있으며, 텍스처 이름 규칙을 예로 들면:
- 텍스처는 반드시 T_*로 시작
- 텍스처 적용 타입에 따라 _c 또는 _d로 종료
즉, AND/OR 연산자로 구성된 두 가지 제한 조건이 필요합니다: (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를 체크하면 이 규칙과 매칭되지 않는 리소스를 기록합니다:
result.json
{
"matchedAssets":[
{
"ruleName":"Texture2D_Name_Rule",
"ruleDescribe":"texture name need startwith \\"T_\\"",
"ruleId":0,
"assetPackageNames":[
"/Game/Mannequin/Character/Textures/UE4_LOGO_CARD",
"/Game/Mannequin/Character/Textures/UE4_Mannequin__normals",
"/Game/Mannequin/Character/Textures/UE4_Mannequin_MAT_MASKA",
"/Game/Mannequin/Character/Textures/UE4Man_Logo_N",
"/Game/Texture/20210914162516"
]
}
]
}
경로 매칭
특정 타입의 리소스가 지정된 경로에 저장되어 있는지 검사하는 것도 가장 많이 사용되는 규칙 중 하나입니다. 마찬가지로 여러 경로 규범을 지원하며, 각 규범은 기본적으로 두 가지 모드를 지원합니다:
- WithIn
- Wildcard
특정 디렉토리에 위치하는지 또는 경로가 와일드카드 규칙을 만족하는지 검사할 수 있습니다. Texture를 예로 들어, Texture가 모두 */Textures/*라는 이름의 디렉토리에 저장되어 있는지 검사합니다:
*/Textures/*의 와일드카드 검사를 제공하며, bReverseCheck를 체크하면 이 규칙과 매칭되지 않는 리소스를 기록합니다:
result.json
{
"matchedAssets":[
{
"ruleName":"Texture2D_Path_Rule",
"ruleDescribe":"Texture nedd within */Textures/* folder.",
"ruleId":1,
"assetPackageNames":[
"/Game/Mannequin/Character/Materials/MaterialLayers/T_ML_Rubber_Blue_01_D",
"/Game/Mannequin/Character/Materials/MaterialLayers/T_ML_Rubber_Blue_01_N",
"/Game/Mannequin/Character/Materials/MaterialLayers/T_ML_Aluminum01",
"/Game/Mannequin/Character/Materials/MaterialLayers/T_ML_Aluminum01_N",
"/Game/Texture/20210914162516",
"/Game/Texture/T_20210914162516"
]
}
]
}
속성 매칭
특정 리소스에서 특정 옵션이 활성화되어 있는지 또는 특정 속성의 값을 검사하는 것은 리소스 규정 준수 검사의 핵심입니다. 마찬가지로 리소스 속성 검사에도 여러 규칙을 추가할 수 있습니다.
저는 리플렉션을 기반으로 리소스의 속성 매칭 메커니즘을 구현했습니다. 임의의 리소스 타입에 대해 리플렉션 마크가 있는 속성이라면 속성명과 검사값을 통해 매칭할 수 있으며, 값의 검사에 대해 두 가지 모드를 제공합니다:
- Equal
- NotEqual
저는 리플렉션을 기반으로 리소스의 속성 매칭 메커니즘을 구현했습니다. 임의의 리소스 타입에 대해 리플렉션 마크가 있는 속성이라면 속성명과 검사값을 통해 매칭할 수 있으며, 값의 검사에 대해 두 가지 모드를 제공합니다:
- Equal
- NotEqual
예를 들어: CompressionSettings가 TC_Default로 설정되어 있고 그리고 CompressionQuality가 TCQ_Highest 또는 TCQ_High로 설정된 텍스처입니다. 앞서 MatchLogic을 통해 배열로 논리 처리 과정을 구현하는 방법을 소개했으며, 속성 검사에서도 매우 중요합니다.
매칭되는 리소스를 검사할 수 있습니다:
{
"matchedAssets": [
{
"ruleName":"Texture_CompressSetting_Rule",
"ruleDescribe":"Texture2D need Set Compress",
"ruleId":2,
"assetPackageNames": [
"/Game/Texture/20210914162516"
]
}
]
}
주의: 속성 매칭은 속성의 리플렉션 이름을 기반으로 검사합니다. UE에는 DisplayName이 있어 에디터에서 표시되는 이름이 실제 리플렉션 이름과 일치하지 않을 수 있으므로 주의가 필요합니다. (플러그인은 속성 선택을 지원합니다)
속성 매칭은 리플렉션 기반의 속성 패널 커스터마이징을 구현했습니다. UClass를 선택한 후 모든 리플렉션 속성을 자동으로 나열하고, 선택한 속성명에 따라 에디터에서 속성명의 에디터 타입을 자동으로 생성하여 매우 놀랍습니다:
제출 권한 매칭
저장소 내 리소스 파일의 수정 권한 검사를 지원하며, 특정 타입의 리소스를 특정 인원만 수정할 수 있도록 제한할 수 있습니다. 예를 들어 프로젝트의 마스터 머티리얼은 TA 팀만 수정할 수 있도록 합니다.
검사의 두 가지 모드:
- Git 내 제출 정보 기반
- 기기 사용자명 기반
Git 기반 시 제출 대기 파일 및 해당 파일의 최근 제출 기록의 제출자를 가져올 수 있습니다.
기기 사용자명 기반 시 현재 기기의 사용자명을 가져와 StartsWith 검사를 수행합니다. 일부 기기명에 lipengzha-PC와 같은 접미사가 포함될 수 있기 때문입니다.
Editor에서의 검사 알림:
사용자 정의 규칙
앞서 제가 제공한 몇 가지 기본 매칭 규칙을 소개했지만, 특수한 검사 요구사항이 있는 경우 편리한 확장 방법을 제공합니다. UOperatorBase 클래스를 상속하고 Match 함수를 오버라이드하여 사용자 정의 검사 요구사항을 구현할 수 있습니다.
UCLASS(Blueprintable,BlueprintType)
classUOperatorBase :public UObject
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintImplementableEvent,BlueprintCallable)
boolMatch(UObject* Object,const FString& AssetType);
};
현재 리소스의 UObject와 문자열 FString AssetType이 전달되며, 이 두 데이터를 통해 사용자 정의 검사를 수행할 수 있습니다.
Rule의 CustomRules에서 사용할 클래스(TSubclassOf<UOperatorBase>)를 지정합니다:
사용자 정의 규칙
물론 UOperatorBase를 상속하여 블루프린트 클래스를 생성하고 오버라이드를 구현할 수도 있어 더욱 편리합니다:
스캔을 실행할 때 지정된 클래스의 CDO를 가져와 Match 함수를 호출하고 매칭 결과를 얻습니다.
예를 들어 맵의 GameMode 설정 검사와 같은 요구사항은 사용자 정의 규칙을 통해 구현할 수 있습니다:
예를 들어 NeverCook 디렉토리의 리소스를 참조한 경우 알림을 주어, 의존 리소스가 패키징되지 않아 발생하는 표현 이상을 방지합니다:
매칭 후처리
플러그인은 매칭 규칙 실행 후 후처리 지원을 제공합니다. 예를 들어 비규범 리소스 속성의 자동 설정, 자동 이름 변경 등의 요구사항에 대응할 수 있습니다. 매칭 결과를 가져올 수 있어야 합니다.
각 FScannerMatchRule에 UScannnerPostProcessorBase 클래스를 지정하는 인터페이스를 제공했습니다. 매칭 규칙의 리소스를 처리하려면 UScannnerPostProcessorBase 클래스를 상속하여 Processor 함수를 구현하면, 현재 규칙 스캔 완료 후 스캔 결과가 전달됩니다.
for(constauto& PostProcessorClass:Rule.PostProcessors)
{
if(IsValid(PostProcessorClass))
{
UScannnerPostProcessorBase* PostProcessorIns =Cast<UScannnerPostProcessorBase>(PostProcessorClass->GetDefaultObject());
if(PostProcessorIns)
{
PostProcessorIns->Processor(RuleMatchedInfo,Rule.ScanAssetType->GetName());
}
}
}
최종 스캔 결과
모든 규칙 스캔이 완료되면 결과는 FMatchedResult 구조체이며, 각 규칙이 매칭한 리소스 목록을 기록하는 FRuleMatchedInfo 데이터를 포함합니다:
// Rule Matched info
USTRUCT(BlueprintType)
structFRuleMatchedInfo
{
GENERATED_USTRUCT_BODY()
public:
FRuleMatchedInfo():RuleName(TEXT("")),RuleDescribe(TEXT("")),RuleID(-1){}
UPROPERTY(EditAnywhere,BlueprintReadWrite)
FString RuleName;
UPROPERTY(EditAnywhere,BlueprintReadWrite)
FString RuleDescribe;
// 该规则在配置数组中的下标
UPROPERTY(EditAnywhere,BlueprintReadWrite)
int32 RuleID;
UPROPERTY(EditAnywhere,BlueprintReadWrite, transient)
TArray<FAssetData> Assets;
UPROPERTY(EditAnywhere,BlueprintReadWrite)
TArray<FString> AssetPackageNames;
};
// final result
USTRUCT(BlueprintType)
structFMatchedResult
{
GENERATED_USTRUCT_BODY()
public:
UPROPERTY(EditAnywhere,BlueprintReadWrite)
TArray<FRuleMatchedInfo> MatchedAssets;
};
a
확장
RuleName, RuleDescribe, RuleID를 통해 리소스가 어느 규칙에 매칭되었는지 쉽게 확인할 수 있습니다.
최종적으로 이 구조체는 Json으로 직렬화되어 출력됩니다. 원시 결과를 얻거나 특별한 처리를 하려면 UResScannerProxy에서 GetScanResult()를 호출하여 가져올 수 있습니다.
자동화 검사
ResScannerUE는 Commandlet 실행 방법을 제공하며, 설정 파일을 지정하여 시작할 수 있습니다:
UE4Editor-cmd.exe PROJECT_NAME.uproject -run=ResScanner -config="res_scanner.json"
-wait 파라미터를 추가하면 실행 완료 후 입력을 대기하여 결과를 미리 볼 수 있습니다.
제가 이전에 오픈소스로 공개한 도구인 UELauncher를 사용하면 설정을 비교적 쉽게 구현할 수 있습니다:
ResScannerUE 기반 자동화 스캔 실습은 제 다른 글을 참고하세요: ResScannerUE 기반 리소스 검사 자동화 실습
업데이트 로그
2022.08.02 v25
ResScannerUE 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 패널에서 구체적인 타입에 따라 속성 생성- 멀티스레드 규칙 검사, 병렬화 처리
Original Post
UE资源合规检查工具ResScannerUE
在游戏项目开发中,因为资源量大,涉及人员广,比较难自觉地统一资源规范,如果资源出现问题,手动排查要花费大量的人力,这也是资源管理的风险和痛点。基于这种需求,我开发了一款编
imzlp.com
'TECH.ART.FLOW.IO' 카테고리의 다른 글
"Advanced Horse IK Solution" related of tech for Study lists. (0) | 2025.10.13 |
---|---|
[번역] UE5 Virtual Assets 가용성 분석 (0) | 2025.10.12 |
[YOUTUBE] 컴퓨터 그래픽의 선구자들. (0) | 2025.10.02 |
[번역] 효율적인 ZSTD Shader 딕셔너리 학습 방안 (0) | 2025.09.24 |
명조 퍼블릭 MMD 다운로드 페이지. (3) | 2025.09.23 |