资源引用丢失


在增量编译过程中如果Unity闪退了,除了会产生导致崩溃的问题资源,也会导致一些不那么严重、但是非常奇怪的渲染结果:屏幕渲染出现紫块或者渲染效果异常,通过scanref也可以发现问题。

比如上次我们制作了一把KFC主题的战斗刀,Editor里面看到是正常的

但是真机运行的时候就比较奇怪了,明显刀刃的贴图错了,并且刀把的质感也不是特别好。

这种情况下使用scanref检查一遍资源引用,发现了问题

find . -iname '*.pak' | xargs abtool scanref

从日志看,资源dynamic/module/kfc!7!forcedownload!cod_models$weapons$meleeweapon$meleeweapon_014_knifes$cn2!0.pak引用了另外一个ab资源dynamic/module/common!7!forcedownload!cod_models$weapons$meleeweapon$meleeweapon_014_knifes$5!0.pak里面索引为6贴图,但是后者资源里面并没有这个贴图,那么这种情况需要把资源dynamic/module/common!7!forcedownload!cod_models$weapons$meleeweapon$meleeweapon_014_knifes$5!0.pak从构建机删掉重新打包。

定位这个问题,还可以从另外一个角度入手。首先通过saveobj命令保存资源的基本信息。

find . -iname '*.pak' | xargs abtool saveobj

然后通过getref -r命令直接查找出问题的材质球引用的资源列表,其中-r参数表示查找逆向下游资源的引用列表,没有-r参数情况下该命令查找当前资源的上游引用列表。

那么也能发现KnifeS_KFC.mat引用第五个贴图在目标资源dynamic/module/common!7!forcedownload!cod_models$weapons$meleeweapon$meleeweapon_014_knifes$5!0.pak里面找不到,两种方法得到同样结果。

上面被丢失的资源是贴图,如果丢失的资源是材质球,那么就会表现为屏幕紫块,定位方式类似。需要说明的是,上面提到的资源引用丢失问题指的是资源引用在,但是目标资源不存在的情况,如果原始资源引用指针为空,那么这种问题在开发阶段阶段就能发现,当然工具也能发现引用为空的情况。

为了确认资源指针是否为空,我们需要用到另外一个命令edit

abtool edit dynamic/module/kfc\!7\!forcedownload\!cod_models\$weapons\$meleeweapon\$meleeweapon_014_knifes\$cn2\!0.pak

然后进入命令行交互模式,在这种模式可以执行lua脚本,比如可以输入lua file:dump_object(2),其中2KnifeS_KFC.mat的资源索引,通过getref命令得到的。

$ lua file:dump_object(2)
<Material:21> id=2
    m_Name:string = KnifeS_KFC
    m_Shader:PPtr<Shader>
        m_FileID = 5
        m_PathID = 34
    m_ShaderKeywords:string = _DYNAMIC_ADVANCE_DETAIL_LERP
    m_LightmapFlags:uint32_t = 4
    m_EnableInstancingVariants:bool = 1
    m_DoubleSidedGI:bool = 0
    m_CustomRenderQueue:int32_t = -1
    stringTagMap:map<string,string>
    disabledShaderPasses:vector<string>
    m_SavedProperties:UnityPropertySheet
        m_TexEnvs:map<string,UnityTexEnv>
            first:string = _AlphaMap
            second:UnityTexEnv
                m_Texture:PPtr<Texture>
                    m_FileID = 0
                    m_PathID = 0
                m_Scale:Vector2f
                    x:float = 1
                    y:float = 1
                m_Offset:Vector2f
                    x:float = 0
                    y:float = 0
            first:string = _BentNormalMap
            second:UnityTexEnv
                m_Texture:PPtr<Texture>
                    m_FileID = 0
                    m_PathID = 0
                m_Scale:Vector2f
                    x:float = 1
                    y:float = 1
                m_Offset:Vector2f
                    x:float = 0
                    y:float = 0
            first:string = _BumpMapPakced
            second:UnityTexEnv
                m_Texture:PPtr<Texture>
                    m_FileID = 1
                    m_PathID = 4
                m_Scale:Vector2f
                    x:float = 1
                    y:float = 1
                m_Offset:Vector2f
                    x:float = 0
                    y:float = 0
            first:string = _CutRimTex
            second:UnityTexEnv
                m_Texture:PPtr<Texture>
                    m_FileID = 0
                    m_PathID = 0
                m_Scale:Vector2f
                    x:float = 1
                    y:float = 1
                m_Offset:Vector2f
                    x:float = 0
                    y:float = 0
            first:string = _DetailAlbedoMap
            second:UnityTexEnv
                m_Texture:PPtr<Texture>
                    m_FileID = 4
                    m_PathID = 3
                m_Scale:Vector2f
                    x:float = 3
                    y:float = 3
                m_Offset:Vector2f
                    x:float = -0.15
                    y:float = 0.8
            first:string = _DetailNormalMap
            second:UnityTexEnv
                m_Texture:PPtr<Texture>
                    m_FileID = 0
                    m_PathID = 0
                m_Scale:Vector2f
                    x:float = 1
                    y:float = 1
                m_Offset:Vector2f
                    x:float = 0
                    y:float = 0
            first:string = _EmissionMap
            second:UnityTexEnv
                m_Texture:PPtr<Texture>
                    m_FileID = 0
                    m_PathID = 0
                m_Scale:Vector2f
                    x:float = 1
                    y:float = 1
                m_Offset:Vector2f
                    x:float = 0
                    y:float = 0
            first:string = _HeightMap
            second:UnityTexEnv
                m_Texture:PPtr<Texture>
                    m_FileID = 0
                    m_PathID = 0
                m_Scale:Vector2f
                    x:float = 1
                    y:float = 1
                m_Offset:Vector2f
                    x:float = 0
                    y:float = 0
            first:string = _MainTex
            second:UnityTexEnv
                m_Texture:PPtr<Texture>
                    m_FileID = 1
                    m_PathID = 5
                m_Scale:Vector2f
                    x:float = 1
                    y:float = 1
                m_Offset:Vector2f
                    x:float = 0
                    y:float = 0
            first:string = _MetallicRoughnessMap
            second:UnityTexEnv
                m_Texture:PPtr<Texture>
                    m_FileID = 2
                    m_PathID = 6
                m_Scale:Vector2f
                    x:float = 1
                    y:float = 1
                m_Offset:Vector2f
                    x:float = 0
                    y:float = 0
            first:string = custom_IBLCubemap
            second:UnityTexEnv
                m_Texture:PPtr<Texture>
                    m_FileID = 3
                    m_PathID = 4
                m_Scale:Vector2f
                    x:float = 1
                    y:float = 1
                m_Offset:Vector2f
                    x:float = 0
                    y:float = 0

在Unity资源里面通过PPtr<T>表示一个资源引用,比如,上面丢失的_MetallicRoughnessMap贴图,它的指针有两个字段:m_FileID表示目标资源的文件索引,m_PathID表示目标资源在目标文件里面的资源索引ID,其中m_FileID可以通过SerializedFile的metadata里面可以索引到一个全局唯一的路径archive:/cab-3fc774b79be2c61a94690dbb2913f522/cab-3fc774b79be2c61a94690dbb2913f522,这样通过m_FileIDm_PathID两个字段可以全局确定一个唯一的资源对象。

first:string = _MetallicRoughnessMap
second:UnityTexEnv
    m_Texture:PPtr<Texture>
        m_FileID = 2
        m_PathID = 6

m_FileID=0表示当前资源指针指向当前文件内的资源对象,m_PathID=0表示当前资源指针为空,这时通过Unity的Inspector可以看到资源的槽位是空的,所以如果发现某个资源指针的m_PathID=0那么这就是一个资源空引用案例,如下所示。

first:string = _HeightMap
second:UnityTexEnv
    m_Texture:PPtr<Texture>
        m_FileID = 0
        m_PathID = 0

results matching ""

    No results matching ""