Programmable Resource Check Tool
The goal we sought to fulfill when designing it was to provide some set functions, which users could combine to tackle various resource checks. Every project team has its own understanding of what makes a resource good, and good resources should have something in common. Project teams can share their check rules with each other.
Usage
Please open from the console
sac.exe [Project Path] Run resource checks with default rules
sac.exe D:\game\Assets
-s [Project Path] Specify a project path
-r [Rule Path] Check with custom rules
sac.exe -s D:\game\Assets -r myrule.yaml
Syntax:
Try to keep the syntax similar to Python, and follow the rules of YAML
WhitePath: # Whitelist. It takes regular expressions. Each of the following paths is matched with a regular expression If there’s no Whitelist, also annotate this line
- ".*prefab"
- "*.obj"
# Used globally if not written here
BlackPath: # Blacklist If there’s no Blacklist, also annotate this line
- ".*.prefab"
# - "*.obj"
# No Blacklist if you don’t write it
# Configure each rule according to the Path Whitelist and Blacklist
# You can describe which rules apply on which paths here
PathRule:
- Rules:
- Material_GPUInstance
- Material_lit
- Prefab1
White: # Whitelist. It takes regular expressions. Each of the following paths is matched with a regular expression If there’s no Whitelist, also annotate this line
- .*mat
Black: # Blacklist If there’s no Blacklist, also annotate this line
- '.*'
Enable: True #Means use this rule This line is used by default if you don’t write it
- Rules:
- Material_URP
- Material_workFlow
White:
- .*mat
# If there is both a Blacklist and a Whitelist, both need to be satisfied
###############################
# Register your custom rules here
Material:
- Material_lit
- Material_GPUInstance
Prefab:
- Prefab_layer
###############################
# Below is the custom rule
# If ShaderName is Universal Render Pipeline/Lit
# You must select AlphaClipping If the self-glow color is black, the glow map cannot be bound
Material_lit:
- shaderName = GetShaderName()
- if shaderName == "Universal Render Pipeline/Lit":
- WriteWithPath("Shouldn’t use Lit type shader")
# If shader is Universal Render Pipeline/Lit, Universal Render Pipeline/FX/ADDAphaBlend_Decal, Universal Render Pipeline/SpeedTree8
# You must start GPUInstance
Material_GPUInstance:
- shaderName = GetShaderName()
- if shaderName:
- if Any(shaderName,"Universal Render Pipeline/Lit","Universal Render Pipeline/FX/ADDAphaBlend_Decal","Universal Render Pipeline/SpeedTree8"):
- if GetEnableGPUInstance() == 0:
- WriteWithPath("GPUInstance unstarted")
# If a Prefab contains other Prefabs, and if there are collider components, and Layer is Default, you need to set Layer as GroundTerrain
Prefab_layer:
- if IsIncludeAnotherPrefab():
- if IsColliderExist():
- if GetRootLayer() == 0:
- WriteWithPath("If a nested Prefab contains colliders, and Layer is Default, you need to set Layer as GroundTerrain")
Texture: # Means the following rules will apply on resources of the Prefab type When a Prefab type resource is parsed, this rule will auto apply to it
- if AttributeIsTarget("mipMapMode",0):
- WriteWithPath("mipMapMpde_is_zero")
Material means this type will apply on the Material type resources. When the program loads a Material, it will find and run this rule.
As shown above, it checks which Materials use the Lit type shader and saves the path to the output result. The result should be as follows: :
- D:SRP_Run\Assets\Meterial\m1.mat: Shouldn’t use Lit type shader
- D:SRP_Run\Assets\Meterial\m2.mat: Shouldn’t use Lit type shader
Key Function
The string should be quoted in double quotation marks.
View “mipMapMode”, “mipMaps” and other attribute names in the resource file
General Function
A general function is a function that all types can use
Function Name | Usage |
---|---|
GetSubAttribute(x,"mipMapMode") | Obtains the target attribute from the given dictionary X, recursively looking down |
GetAttributeByName("mimaps") | Obtains the target attribute |
GetSize() | Size of the obtained resource (kb) |
GetGUID() | Obtain GUID |
GetPath() | Return Path |
Call("ruleName",guid) | Call other resource check, e.g.check a certain Texture of the current Prefab |
WriteWithPath("xxxxx",...) | Save “xxxxx” and output it to the local directory. This function supports limitless parameters but the string should not contain spaces |
Print("xxxx",....) | Outputs “xxxxx”. Supports limitless parameters |
AttributeIsTarget("attribute",1) | If Attribute is the target, return True |
Any(p1,p2,p3....) | If there is any True and non-zero value, return True |
AnyCount(p1,p2.....) | Number of True, non-zero values returned |
AnyEqual(p1,p2,p3...) | If P1 equals any of the following values, return True |
AnyEqualCount(p1,p2,p3....) | Return the number of following values equalling P1 |
if else for > = < == != not and | Same as Python, for if, None, False or 0 are False, others are True |
in ,not in | Same as Python, can be used to operate strings, arrays, "a" in "abc" --> True |
+ - * / | Same as Python, elementary arithmetic |
len(a) | Same as Python, returns array length but cannot create arrays. Arrays are the return values of system functions. |
continue break | |
Don’t use arithmetic operators in succession on the same line, e.g., a=1+2+3. Write it as a=1+(2+3)
Exclusive Functions
Texture
Texture refers to files of the following formats:
('.bmp', '.gif', '.hdr','.iff', '.jpg', '.jpeg','.pict', '.png', '.psd','.tga', '.tiff', '.tif','.exr')
Function Name | Usage |
---|---|
GetTextureType() | Return the Texture type: please consult TextureType for the meaning of the return value |
GetTextureShape() | Return the Texture shape: please consult TextureShape for the meaning of the return value |
GetSizeForDefault() | Return its default size |
GetSizeForAndroid() | Return its size on Android |
GetSizeForStandalone() | Return its size under Standalone |
GetResizeAlgorithmForDefault() | Return its default compression algorithm: 0 for Mitchell, 1 for Billinear |
GetResizeAlgorithmForAndroid() | Return its compression algorithm on Android: 0 for Mitchell, 1 for Billinear |
GetResizeAlgorithmForStandalone() | Return its compression algorithm under Standalone: 0 for Mitchell, 1 for Billinear |
GetCompressionForDefault | Return its default compression level. 0: None, 1: Normal Quality, 2: High, 3: Low |
GetCompressionForAndroid | Return the Android compression level |
GetCompressionForStandalone | Return the Standalone compression level |
GetFormatForDefault | Default format. Please consult TextureFormat for the meaning of the return value |
GetFormatForStandalone | Format under Standalone |
GetFormatForAndroid | Format on Android |
GetSRGBAttribute() | Acquire whether it is SRGB: 0 for No, 1 for Yes |
GetAlphaSource() | Acquire its AlphaSource: please contact AlphaSouce for the meaning of the return values |
GetAlphaIsTransparency() | If Alpha is transparent: 0 for No, 1 for Yes |
GetIgnorePngGramma() | If you selected to ignore pngGramma:0,1 |
GetReadWriteEnable() | Readable and writable:0,1 |
GetStreamingMipmaps() | 0,1 |
GetVirtualTextureOnly() | 0,1 |
GetWrapU() | 0:Repect, 1:Clamp, 2:Mirror, 3:MirrorOnce |
GetWrapV() | Same as above |
GetWrapW() | Same as above |
GetAnsioLevel() | |
GetMipMapFiltering() | 0: Box, 1:Kaiser |
GetBorderMipMaps() | 0,1 |
GetFadeoutMipMaps() | 0,1 |
GetMipMapsPreserveCoverage() | 0,1 |
GetAlphaCutoffValue() | Value |
Return Types Cross Reference:
TextureType :
- 0 : Default
- 1 : NormalMap
- 2 : EditorGUIandLegacyGUI
- 4: Cookie
- 6 : lightMap
- 7 : Cursor
- 8 : Sprite(2D and ui)
- 10 : SingleChannel
- 11: ShadowMask
- 12: DirectionalLightmap
TextureShape :
- 1: 2D
- 2: Cube
- 4: 2D Array
- 8: 3D
AlphaSource
- 0: None
- 1: Input Texture Alpha
- 2: From Gray Scale
TextureFormat
- -1: Automatic
- 4: RGBA32
- 7: RGB16
- 3: RGB24
- 63: R8
- 9: R16
- 1: Alpha8
Material
Material refers to files of the following format:
('.mat', )
Function Name | Usage |
---|---|
GetShaderName() | Return the name of shader it owns, e.g. “Unlit/custom" |
GetTextureByName("name") | Acquire the Texture; This function should not be used currently and its return value should be used in conjunction with GetSubAttribute |
GetTextureGuidByName("name") | Acquire its Texture GUID; If there is none, return 0. You can judge from this whether a map is bound |
ColorEqual("tar",1,1,1,1) | Whether the color tar’s RGBA equals the parameters behind. If yes, return False. If the parameter is -1, this item will not be compared |
GetEnableGPUInstance() | Return whether GPUInstance is on, 0: No, 1: Yes |
GetDoubleSideGI() | Whether DoubleSidedGlobalIIIumination is on, 0 No, 1: Yes |
GetTextureNameInShader() | Acquire Texture names referenced in Shader |
GetTextureNameInMaterial() | Acquire Texture names referenced in Material |
For Material: If you want to get a variable on the panel called Threshold, it is Float or int:
GetAttributeByName("Threshold") # The function will return the value of the threshold
For color types on the panel:
ColorEqual("tar",1,1,1,1) # This function will compare the target color with the following four values, respectively RGBA. True will be returned if they all equal. If any of the four is not to be compared, set it as -1.
# If you want a higher level of color customization
x = GetAttributeByName("tar") # This function will return the color’s original stats
r = GetSubAttribute(x,'r') # Thus, you will get detailed stats
g = GetSubAttribute(x,'g')
b = GetSubAttribute(x,'b')
a = GetSubAttribute(x,'a')
Prefab
Prefab refers to files of the following format:
('.prefab')
Function Name | Usage |
---|---|
IsComponentExist("Transfrom") | Whether the target component is there. Search through the Prefab |
IsGameObjectHasComponent("GameObjName","ComName") | Whether there are the target components in the target GameObject |
GetAllComponentByGameObjectName("GameObejctName") | Return all components’ names according to GameObject |
GetComponentByGameObject("GameObjectName","ComponentName") | Return target GameObject’s target component. The return value is a dictionary |
GetComponentByName('ComponentName') | Return the first component found. This is a dictionary |
GetGameObjectByName("Name") | Get the target GameObject. The return value is a dictionary and should be processed with GetSubAttribute |
GetRootLayer() | Get the Layer of Prefab’s root GameObject |
GetLayerByName("GameObjName") | Get the Layer of the target GameObject. It should 1, 2, 3 or 4 |
GetRootTag() | Return the tag of the root GameObject |
GetTagByName("GameObjName") | Return the tag of the target GameObject. The result is a string |
GetRootName() | Return the name of the root GameObject |
IsColliderExist() | Whether there is a Collider inside |
IsIncludeAnotherPrefab() | Whether there is another Prefab inside (Whether this is a nested Prefab) |
GetNameByFileID(fileID) | Get the name of components, or of GameObject according to file ID |
GetSubGameObjectName("Name") | Return the name of a first-level sub-object of the target GameObject |
GetGameObjectNameByComponentID(fileID) | Return the component’s file ID and the name of the GameObject it belongs to |
GetGameObjectByName | |
IsTransformPositionEqual(Transform,0,0,0) | Determine if the Position of Transform is equal to the latter. -1 means the bit is not involved in comparison. Transform is the Component acquired in the last step |
IsTransformScaleEqual(Transform,1,1,-1) | Same as above |
IsTransformRotationEqual(Transform,1,1,1,-1) | Same as above. Note that Rotation has four bits, with the last by default 1, i.e. when not rotating, it is (0,0,0,1) |
Prefab is a rather complex type. For most demands, use
GetAllComponentByGameObjectName()
GetComponentByName()
These two functions are enough to handle most cases
Note that GetComponentByName() returns a dictionary. For the time being you can only process this return value with GetSubAttribute()
a = GetComponentByName("Sphere","MeshRenderer")
x = GetSubAttribute(a,"m_CastShadows")
For the time being, you can only find the attribute name m_CastShadows in .prefab files. m_CastShadow corresponds to CastShadow in the attribute panel.
A mapping table will then be created internally, enabling you to use the attribute names you see on the attribute panel.
Animation
Animation refers to the files of the following format:
('.anim')
None. General functions can be used if and AttributeIsTarget are enough for most tasks
Video
Video refers to the files of the following formats:
('.webm','.mpg','.mp2','.mpeg','.mpe','.mpv','.ogg','.mp4','.m4p','.m4v','.avi','.wmv','mov','.qt','.flv','.swf')
Function Name | Usage |
---|---|
GetSRGB() | Whether SRGB is on: 0, 1 |
GetTranscodeForDefault() | Whether Transcode is on on the default platform: 0, 1 |
GetTranscodeForStandalone() | Whether Transcode is on on PC/Standalone: 0, 1 |
getTranscodeForAndroid() | Whether Transcode is on on Android: 0, 1 |
GetBitRateModeForDefault() | Default Bitrate mode: 0: Low, 1: Medium, 2: High |
GetBitRateModeForStandalone() | Same as above |
GetBitRateModeForAndroid() | Same as above |
GetCodecForDefault() | Coding mode on the default platform: consult Codec for the meaning of the return value |
GetCodecForStandalone() | Same as above |
GetCodecForAndroid() | Same as above |
GetDimensionsForDefault() | Dimensions attributes on the default platform: consult Dimensions for the meaning of the return value |
GetDimensionsForStandalone() | Same as above |
GetDimensionsForAndroid() | Same as above |
GetAspectRatioForDefault() | AspectRatio attributes on the default platform: 0 for No Scaling, 5 for Stretch |
GetAspectRatioForStandalone() | Same as above |
GetAspectRatioForAndroid() | Same as above |
GetWidthForDefault() | Width under default, only makes sense when Dimensions are CustomSize |
GetWidthForStandalone() | Same as above |
GetWidthForAndroid() | Same as above |
GetHeightForDefault() | Height under default, only makes sense when Dimensions are CustomSize |
GetHeightForStandalone() | Same as above |
GetHeightForAndroid() | Same as above |
GetSpatialQualityForDefault() | SpatialQuality Grade under default. Consult SpatialQuality for the meaning of the return value |
GetSpatialQualityForStandalone() | Same as above |
GetSpatialQualityForAndroid() | Same as above |
GetFlipHorizontally() | Get whether Flip Horizontally is selected |
GetFlipVertical() | Get whether Flip Vertically is selected |
GetDeinteriace() | Get Deinterlace: 0: off, 1: even, 2: odd |
GetImportAudio() | Get whether ImportAudio is selected |
Codec
- 0: Auto
- 1: H264
- 2: VP8
- 3: H265
Dimensions
- 0: Original Size
- 1: ThreeQuarterRes
- 2: HalfRes
- 3: QuarterRes
- 4: Square1024
- 5: Square512
- 6: Square256
- 7: CustomSize
SpatialQuality
- 0: Low Spatial Quality
- 1: Medium Spatial Quality
- 2: High Spatial Quality
Audio
Audio refers to the files of the following formats:
('.mp3','.ogg','.wav','.aiff','.aif','.mod','.it','.s3m','.xm')
Function Name | Usage |
---|---|
GetForceToMono | Whether ForceToMono is selected. Return 0, 1 |
GetLoadInBackGround | Whether LoadInBackGround is selected. Return 0, 1 |
GetAmbisonic | Whether Ambisonic is selected. Return 0, 1 |
GetNormalize | Whether Normalize is selected. Return 0, 1 |
GetPreloadAudioData | Whether Preload Audio Data is selected. Return 0, 1 |
GetLoadTypeForDefault | LoadType on the default platform. Please consult LoadType for the meaning of the return value |
GetLoadTypeForStandalone | Same as above |
GetLoadTypeForAndroid | Same as above |
GetCompressionFormatForDefault | CompressionFormat on the default platform. Please consult CompressionFormat for the meaning of the return value |
GetCompressionFormatForStandalone | Same as above |
GetCompressionFormatForAndroid | Same as above |
GetQualityForDefault | Return the quality under default, only makes sense when CompressionFormat is Vorbis |
GetQualityForStandalone | Same as above |
GetQualityForAndroid | Same as above |
GetSampleRateSettingForDefault | SampleRateSetting under default. Please consult SampleRateSetting for the meaning of the return value |
GetSampleRateSettingForStandalone | Same as above |
GetSampleRateSettingForAndroid | Same as above |
GetSampleRateForDefault | SampleRate under default, only makes sense when SampleRateSetting is OverrideSampleRate |
GetSampleRateForStandalone | Same as above |
GetSampleRateForAndroid | Same as above |
LoadType
- 0: Decompress On Load
- 1: Compressed In Memory
- 2: Streaming
CompressionFormat
- 0: PCM
- 1: Vorbis
- 2: ADPCM
SampleRateSetting
- 0: PreserveSampleRate
- 1: OptimizeSampleRate
- 2: OverrideSampleRate
Model
!!Please read this first!! For unknown reasons, the number of vertices and triangles for a model in the Unity engine does not match what other model-editable software shows, so offline resource check tools cannot get the vertex number in Unity. We are analyzing the Unity source code to try to understand how Unity processes models and we believe this feature will be available soon.
Model refers to the files of the following formats:
('.dae','.3ds','.dxf','.obj','.max','.blend','.lxo')
Function | Usage |
---|---|
GetMeshCompression() | Compression level, 0: Off, 1: Low, 2: Medium, 3: High |
GetReadWriteEnable | Return whether it is readable and writable: 0, 1 |
GetImportVisibility | Return if import Visibility is selected: 0, 1 |
GetImportCameras | Return if Import Cameras is selected: 0, 1 |
GetImportLights | Return if ImportLights is selected: 0, 1 |
GetImportBlendShape | Return if ImportBlendShape is selected |
GetBakeAxisConversion | Return if BakeAxisConversion is selected |
GetScaleFactor | Return ScaleFactor |
GetSortHierarchyByName | Return if SortHierarchyByName is selected |
GetGenerateColliders | Return if GenerateColliders is selected |
GetOptimizeMesh | Consult OptimizeMesh for the meaning of the return value |
GetKeepQuads | Return if keepQuads is selected |
GetWeldVertices | Return if WeldVertices is selected |
GetIndexFormat | Return if IndexFormat is selected |
GetLegacyBlendShapeNormals | Return if LegacyBlendShapeNormals is selected |
GetNormals | Consult Normals for the meaning of the return value |
GetBlendShapeNormals | Meaning of the return value is the same as Normals |
GetNormalsMode | Consult NormalsMode for the meaning of the return value |
GetSmoothnessSource | Consult SmoothnessSource |
GetSmoothingAngle | Return SmoothingAngle |
GetTangents | Consult Tangents for the meaning of the return value |
GetSwapUVs | Return if SwapUV is selected |
GetSubMeshCount | Return SubMesh number |
GetVertexCount | Return vertices number |
OptimizeMesh
- 0: Nothing
- 1: PolygonOrder
- 2: VertexOrder
- 3: PolygonOrder & VertexOrder
- 2147483647: EveryThing
Normals
- 0: Import
- 1: Calculate
- 2: None
NormalsMode
- 0: Unweighted(legacy)
- 1: Unweighted
- 2: AreaWeighted
- 3: AngleWeighted
- 4: AreaAndAngleWeighted
SmoothnessSource
- 0: PreferSmoothingGroup
- 1: FromSmoothingGroup
- 2: FromAngle
- 3: None
Tangents
- 0: Import
- 1: CalculateLegacy
- 2: None
- 3: CalculateMikktspace
- 4: CalculateLegacyWithSplitTangent