可编程资源检测工具
在设计时尽力想实现的目标是,程序提供一些固定的函数,然后用户可以通过这些函数的组合以实现千变万化的资源检测需求,对于什么是一个好的资源这取决于项目组自己的理解,而且好的资源应当具备一些共同的性质,项目组之间可以共享自己的检测规则。
使用方法
请使用控制台打开
sac.exe [工程路径] 使用默认规则进行资源检查
sac.exe D:\game\Assets
-s [工程路径] 指定工程路径
-r [规则路径] 使用自定义规则检查
sac.exe -s D:\game\Assets -r myrule.yaml
语法:
语法尽可能与python相同,并遵循yaml格式的规则
WhitePath: # 白名单,可使用正则表达式,以下每一个路径都会使用正则表达式匹配 如果没有白名单 则请将此行一起注释
- ".*prefab"
- "*.obj"
# 不写则全局使用
BlackPath: # 黑名单 如果没有黑名单 那么请将此行一起注释
- ".*.prefab"
# - "*.obj"
# 不写则没有黑名单
# 根据路径黑白名单详细配置每一条规则
# 你可以在这里描述哪些路径使用哪些规则
PathRule:
- Rules:
- Material_GPUInstance
- Material_lit
- Prefab1
White: # 白名单,可使用正则表达式,以下每一个路径都会使用正则表达式匹配 如果没有白名单 则请将此行一起注释
- .*mat
Black: # 黑名单 如果没有黑名单 那么请将此行一起注释
- '.*'
Enable: True #表示使用使用这条规则 没有此条则默认使用
- Rules:
- Material_URP
- Material_workFlow
White:
- .*mat
# 如果黑白名单同时存在,那么需要同时满足
###############################
# 在这里注册自己的自定义规则
Material:
- Material_lit
- Material_GPUInstance
Prefab:
- Prefab_layer
###############################
# 以下就是自定义规则
# 如果ShaderName为Universal Render Pipeline/Lit
# 则必须勾选AlphaClipping 如果自发光颜色为黑色,则不能绑定发光贴图
Material_lit:
- shaderName = GetShaderName()
- if shaderName == "Universal Render Pipeline/Lit":
- WriteWithPath("不应该使用lit类型的shader")
# 如果shader是Universal Render Pipeline/Lit,Universal Render Pipeline/FX/ADDAphaBlend_Decal,Universal Render Pipeline/SpeedTree8
# 则必须开启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")
# 如果Prefab包含了其他prefab且存在碰撞组件,且layer为Default需将layer设置为GroundTerrain
Prefab_layer:
- if IsIncludeAnotherPrefab():
- if IsColliderExist():
- if GetRootLayer() == 0:
- WriteWithPath("当组合预制体含有碰撞,且Layer为Default,须将Layer设置为GroundTerrain")
Texture: # 表示以下规则将应用在prefab类型的资源上 当解析出来一个prefab类型的资源时 会自动应用此规则
- if AttributeIsTarget("mipMapMode",0):
- WriteWithPath("mipMapMpde_is_zero")
Material表示该类型将应用到Material类型的资源上,当程序加载一个Material时,会找到该规则,并执行他。
以上所示,就是检测哪些Material使用了lit类型的shader,并将路径保存到输出的结果中,最终的结果应该是以下形式的:
- D:SRP_Run\Assets\Meterial\m1.mat: 不应该使用lit类型的shader
- D:SRP_Run\Assets\Meterial\m2.mat: 不应该使用lit类型的shader
关键函数
字符串应当使用 “ ”双引号包围
诸如 “mipMapMode”, “mipMaps”这类属性名请在对应的资源文件中查看
通用函数
通用函数是指所有的类型都可以使用这些函数
函数名 | 用法 |
---|---|
GetSubAttribute(x,"mipMapMode") | 从给定字典x上获取目标属性,递归向下寻找 |
GetAttributeByName("mimaps") | 获取目标属性 |
GetSize() | 获取资源的大小,单位kb |
GetGUID() | 获取GUID |
GetPath() | 返回路径 |
Call("ruleName",guid) | 调用其他的资源检测,比如要对当前Prefab的某一个Texture检测 |
WriteWithPath("xxxxx",...) | 将"xxxxx"保存 并最终输出至本地目录,该函数支持无限个参数,但字符串不应该包含空格 |
Print("xxxx",....) | 输出 "xxxxx",支持无限个参数 |
AttributeIsTarget("attribute",1) | 如果attribute是目标则返回true |
Any(p1,p2,p3....) | 任意一个为True,非0的数值则返回True |
AnyCount(p1,p2.....) | 返回有多少个为True,非0的数值 |
AnyEqual(p1,p2,p3...) | 如果p1,和后面的任意一个相等则返回true |
AnyEqualCount(p1,p2,p3....) | 返回p1和后面多少个相等 |
if else for > = < == != not and | 同python,对于if来说 None,False,0,都是False;其他都是True |
in ,not in | 同python, 可用于操作字符串,数组 ,"a" in "abc" --> True |
+ - * / | 同python 四则运算 |
len(a) | 同python,返回数组长度,但是无法创建数组,数组都是系统函数的返回值 |
continue break | |
算数运算符不要在同一行连续使用:a= 1+2+3 不要这么写,你可以写为a=1+(2+3)
专属函数
Texture
Texutre是指以下格式的文件:
('.bmp', '.gif', '.hdr','.iff', '.jpg', '.jpeg','.pict', '.png', '.psd','.tga', '.tiff', '.tif','.exr')
函数名 | 用法 |
---|---|
GetTextureType() | 返回其Texture类型:返回值的含义请查阅TextureType |
GetTextureShape() | 返回其Texutre形状:返回值的含义请查询TextureShape |
GetSizeForDefault() | 返回其default大小 |
GetSizeForAndroid() | 返回其在安卓平台下的大小 |
GetSizeForStandalone() | 返回其Standlone下的大小 |
GetResizeAlgorithmForDefault() | 返回其default的压缩算法:0表示Mitchell算法,1表示Billinear算法 |
GetResizeAlgorithmForAndroid() | 返回其在Android平台的压缩算法:0表示Mitchell算法,1表示Billinear算法 |
GetResizeAlgorithmForStandalone() | 返回其在Standlone下的压缩算法:0表示Mitchell算法,1表示Billinear算法 |
GetCompressionForDefault | 返回其default的压缩等级,0表示None,1:NormalQuality,2:Hight,3:Low |
GetCompressionForAndroid | 返回Android的压缩等级 |
GetCompressionForStandalone | 返回在standalone的压缩等级 |
GetFormatForDefault | 在default的格式,返回值含义请查询TextureFormat |
GetFormatForStandalone | 在Standalone的格式 |
GetFormatForAndroid | 在android的格式 |
GetSRGBAttribute() | 获取其是否是SRGB:0表示否,1表示是 |
GetAlphaSource() | 获取其AlphaSource: 返回值含义请查询AlphaSource |
GetAlphaIsTransparency() | alpha是否是透明:0表示否,1表示是 |
GetIgnorePngGramma() | 是否勾选了忽视pngGramma:0,1 |
GetReadWriteEnable() | 是否可读可写:0,1 |
GetStreamingMipmaps() | 0,1 |
GetVirtualTextureOnly() | 0,1 |
GetWrapU() | 0:Repect,1:Clamp,2:Mirror,3:MirrorOnce |
GetWrapV() | 同上 |
GetWrapW() | 同上 |
GetAnsioLevel() | |
GetMipMapFiltering() | 0:表示Box,1:表示Kaiser |
GetBorderMipMaps() | 0,1 |
GetFadeoutMipMaps() | 0,1 |
GetMipMapsPreserveCoverage() | 0,1 |
GetAlphaCutoffValue() | 数值 |
返回类型对照表:
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是指以下格式的文件:
('.mat', )
函数名 | 用法 |
---|---|
GetShaderName() | 返回其拥有的shader的名字,形如“Unlit/custom" |
GetTextureByName("name") | 获取其Texture 暂时不应该使用此函数,其返回值应当配合GetSubAttribute使用 |
GetTextureGuidByName("name") | 获取其Texture的GUID 如果没有则返回 0,借此可以判断有没有绑定贴图 |
ColorEqual("tar",1,1,1,1) | 颜色tar的rgba是不是与后面的对应参数相等,全部相等则返回false,若参数是-1则该项不参与对比 |
GetEnableGPUInstance() | 返回是否开启了GPUInstance,0:未开启,1:开启 |
GetDoubleSideGI() | 是否开启了DoubleSidedGlobalIIIumination ,0:未开启,1:开启 |
GetTextureNameInShader() | 获取Shader中引用的Texture名字 |
GetTextureNameInMaterial() | 获取Material里面引用的Texture名字 |
对于Material:如果你想要获取面板上一个名为阈值的变量该变量为Float或者int:
GetAttributeByName("阈值") # 该函数将会返回阈值的数值
对于面板上的颜色类型:
ColorEqual("tar",1,1,1,1) # 该函数将会对比目标颜色与后面的四个数值分别为RGBA,全部相等才会返回True,如果某一位不参与对比,可将此位设置为-1
# 如果你想要对颜色有更高的自定义
x = GetAttributeByName("tar") # 此函数将会返回颜色的原始数据
r = GetSubAttribute(x,'r') # 如此你可以获得 具体的数值
g = GetSubAttribute(x,'g')
b = GetSubAttribute(x,'b')
a = GetSubAttribute(x,'a')
Prefab
Prefab是指以下格式的文件:
('.prefab')
函数名 | 用法 |
---|---|
IsComponentExist("Transfrom") | 是否有目标组件,对整个预制体搜索 |
IsGameObjectHasComponent("GameObjName","ComName") | 目标GameObject是否有目标组件 |
GetAllComponentByGameObjectName("GameObejctName") | 根据GameObject返回其所有的Component的名字 |
GetComponentByGameObject("GameObjectName","ComponentName") | 返回目标GameObject的目标Component,返回值是一个字典 |
GetComponentByName('ComponentName') | 返回找到的第一个Component这是个字典 |
GetGameObjectByName("Name") | 获取目标GameObject返回的是一个字典,应使用GetSubAttribute处理 |
GetRootLayer() | 获取Prefab的根GameObject的Layer |
GetLayerByName("GameObjName") | 获取目标GameObject的layer,结果是0,1,2,3 |
GetRootTag() | 返回根GameObject的tag |
GetTagByName("GameObjName") | 返回目标gameObject的Tag,结果是字符串 |
GetRootName() | 返回根GameObject的Name |
IsColliderExist() | 是否含有碰撞体 |
IsIncludeAnotherPrefab() | 是否包含了另一个预制体(是否是组合预制体) |
GetNameByFileID(fileID) | 根据fileID获取组件的名字,也可以是GameObject的名字 |
GetSubGameObjectName("Name") | 返回目标GameObject的一级子物体的名字 |
GetGameObjectNameByComponentID(fileID) | 返回组件的fileID,返回其所属于的GameObject的名字 |
GetGameObjectByName | |
IsTransformPositionEqual(Transform,0,0,0) | 判断Transform的Position是否等于后者,-1表示该位不参与比对,Transform是上一步获取的Component |
IsTransformScaleEqual(Transform,1,1,-1) | 同上 |
IsTransformRotationEqual(Transform,1,1,1,-1) | 同上,注意Rotation有四位,且最后一位默认1,即不旋转为(0,0,0,1) |
Prefab是一个相当复杂的类型:对于大部分需求你可以使用
GetAllComponentByGameObjectName()
GetComponentByName()
这两个函数即可应用在大部分情况
注意GetComponentByName() 返回的是一个字典,目前其返回值你只能通过GetSubAttribute()处理
a = GetComponentByName("Sphere","MeshRenderer")
x = GetSubAttribute(a,"m_CastShadows")
至于m_CastShadows这个属性名字,目前你只能在.prefab文件中找到,m_CastShadow对应的就是属性面板上的CastShadow
之后内部会建立一个映射表,这样你就可以使用你在属性面板上看到的属性名字了。
Animation
Animation是指以下格式的文件:
('.anim')
无,通用函数即可
if 和 AttributeIsTarget即可执行大部分的任务
Video
Video是指以下格式的文件:
('.webm','.mpg','.mp2','.mpeg','.mpe','.mpv','.ogg','.mp4','.m4p','.m4v','.avi','.wmv','mov','.qt','.flv','.swf')
函数名 | 用法 |
---|---|
GetSRGB() | 是否开启了SRGB:0,1 |
GetTranscodeForDefault() | 在Default平台下是否开启了Transcode:0,1 |
GetTranscodeForStandalone() | 在PC/standalone平台下是否开启了Transcode:0,1 |
getTranscodeForAndroid() | 在Android平台下是否开启了Transcode:0,1 |
GetBitRateModeForDefault() | 在default下的bitrate模式:0:low, 1:medium , 2:high |
GetBitRateModeForStandalone() | 同上 |
GetBitRateModeForAndroid() | 同上 |
GetCodecForDefault() | 在Default平台下的编码模式:返回值含义请查询:Codec |
GetCodecForStandalone() | 同上 |
GetCodecForAndroid() | 同上 |
GetDimensionsForDefault() | 在default平台下的dimensions属性:返回值含义请查询:Dimensions |
GetDimensionsForStandalone() | 同上 |
GetDimensionsForAndroid() | 同上 |
GetAspectRatioForDefault() | 在Default平台下的AspectRatio属性:0:NoScaling,5:Stretch |
GetAspectRatioForStandalone() | 同上 |
GetAspectRatioForAndroid() | 同上 |
GetWidthForDefault() | 在default下的宽度,只在Dimensions为CustomSize时有意义 |
GetWidthForStandalone() | 同上 |
GetWidthForAndroid() | 同上 |
GetHeightForDefault() | 在default下的长度,只在Dimensions为CustomSize时有意义 |
GetHeightForStandalone() | 同上 |
GetHeightForAndroid() | 同上 |
GetSpatialQualityForDefault() | 在default下的SpatialQuality等级,返回值含义请查询:SpatialQuality |
GetSpatialQualityForStandalone() | 同上 |
GetSpatialQualityForAndroid() | 同上 |
GetFlipHorizontally() | 获取是否勾选Flip Horizontally |
GetFlipVertical() | 获取是否勾选Flip Vertically |
GetDeinteriace() | 获取Deinterlace:0:off,1:even,2:Odd |
GetImportAudio() | 获取是否勾选了importAudio |
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
Auido是指以下格式的文件:
('.mp3','.ogg','.wav','.aiff','.aif','.mod','.it','.s3m','.xm')
函数名 | 用法 |
---|---|
GetForceToMono | 是否勾选了ForceToMono,返回0,1 |
GetLoadInBackGround | 是否勾选了LoadInBackGround,返回0,1 |
GetAmbisonic | 是否勾选了Ambisonic,返回0,1 |
GetNormalize | 是否勾选了Normalize,返回0,1 |
GetPreloadAudioData | 是否勾选了Preload Auido Data,返回0,1 |
GetLoadTypeForDefault | 在default平台下的LoadType,返回值含义请查询LoadType |
GetLoadTypeForStandalone | 同上 |
GetLoadTypeForAndroid | 同上 |
GetCompressionFormatForDefault | 在default平台下的CompressionFormat,返回值含义请查询CompressionFormat |
GetCompressionFormatForStandalone | 同上 |
GetCompressionFormatForAndroid | 同上 |
GetQualityForDefault | 返回在default下的quality,只有当CompressionFormat为Vorbis时有意义 |
GetQualityForStandalone | 同上 |
GetQualityForAndroid | 同上 |
GetSampleRateSettingForDefault | 在default下的SampleRateSetting,返回值含义请查询SampleRateSetting |
GetSampleRateSettingForStandalone | 同上 |
GetSampleRateSettingForAndroid | 同上 |
GetSampleRateForDefault | 在default下的SampleRate只在SampleRateSetting为OverrideSampleRate时有意义 |
GetSampleRateForStandalone | 同上 |
GetSampleRateForAndroid | 同上 |
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
!!请先阅读本行!!由于未知原因,在Unity引擎中一个模型的顶点数,三角形数和其他可编辑模型的软件显示的并不一致,所以离线脱机的资源检测工具无法得到Unity中的顶点数,但我们正在分析Unity源码,试图理解Unity是如何处理模型的,相信很快就可以支持本功能。
Model是指以下格式的文件:
('.dae','.3ds','.dxf','.obj','.max','.blend','.lxo')
函数 | 用法 |
---|---|
GetMeshCompression() | 压缩等级,0:off,1:low,2:Medium,3:High |
GetReadWriteEnable | 返回是否可读可写:0,1 |
GetImportVisibility | 返回是否勾选import Visibility:0,1 |
GetImportCameras | 返回是否勾选Import Cameras:0,1 |
GetImportLights | 返回是否勾选ImportLights:0,1 |
GetImportBlendShape | 返回是否勾选ImportBlendShape |
GetBakeAxisConversion | 返回是否勾选BakeAxisConversion |
GetScaleFactor | 返回ScaleFactor |
GetSortHierarchyByName | 返回是否勾选SortHierarchyByName |
GetGenerateColliders | 返回是否勾选GenerateColliders |
GetOptimizeMesh | 返回值含义请查询OptimizeMesh |
GetKeepQuads | 返回是否勾选keepQuads |
GetWeldVertices | 返回是否勾选WeldVertices |
GetIndexFormat | 返回是否勾选IndexFormat |
GetLegacyBlendShapeNormals | 返回是否勾选LegacyBlendShapeNormals |
GetNormals | 返回值含义请查询Normals |
GetBlendShapeNormals | 返回值含义同Normals |
GetNormalsMode | 返回含义请查询NormalsMode |
GetSmoothnessSource | 请查询SmoothnessSource |
GetSmoothingAngle | 返回SmoothingAngle |
GetTangents | 返回值含义请查询Tangents |
GetSwapUVs | 返回是否勾选SwapUV |
GetSubMeshCount | 返回submesh数量 |
GetVertexCount | 返回顶点数 |
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