Skip to content

可编程资源检测工具

在设计时尽力想实现的目标是,程序提供一些固定的函数,然后用户可以通过这些函数的组合以实现千变万化的资源检测需求,对于什么是一个好的资源这取决于项目组自己的理解,而且好的资源应当具备一些共同的性质,项目组之间可以共享自己的检测规则。

使用方法

请使用控制台打开

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