Unity 项目AB资源 重复内容排查

Posted 丛小胖

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity 项目AB资源 重复内容排查相关的知识,希望对你有一定的参考价值。

原因说明:

游戏中资源全部打包ab包进行加载。由于对ab包相应规则理解不正确,可能会导致资源重复被打包。下面介绍下我的排查思路。

资源重复的主要原因 :当ab包打包时,发现依赖资源不再自己的ab包中或者不再其他ab包中,就会复制一份资源到自己的ab包中。

其他原因

  1. 游戏资源被内嵌到包体中了(一般是Resources文件夹中的资源和依赖资源)
  2. Graphics设置中添加了额外的shader。(这里的shader的一定会被嵌入到包体内,可以使用Shader.Find调用),添加到这里会把所有变体编译,被坑过

image.png

1. 准备工作:

1.1 准备好apk/ipa   或者打包好的ab资源

下载游戏的apk包(ipa一样的),将后缀改成zip,解压到文件夹下面。

image.png

1.2 下载资源解析工具:

https://www.perfare.net/1194.html

1.3 解析资源

解析解压的文件,我们就可以apk中所有的资源了:

image.png

image.png

资源解析后如下图:

image.png

2. 具体说明

2.1 最多的坑 standard shader (AB包 standard 清理)

解析资源后会发现有很多重复的standard shader,但是项目中使用的shader都是我们自己写的,根本不会使用系统自带的。最后发现是模型引入的问题。 当模型Materials设置如下两张图的时候,都会讲默认的standard打入到ab包中。

图一:

image.png

图二:

image.png

解决方案:

  1. 引入的时候指定具体的材质球和shader (建议使用该方案)

image.png

  1. 创建一个我们自己使用的材质,给引入的模型

image.png

  1. 提取需要使用的资源(如:mesh,动作等)后,删除fbx

2.2 RawImage组件 或 类似组件的问题

项目使用Packing Tag来组织图集(如图一),RawImage可以直接用原始图赋值(如图二),但打AB包的时候会复制一张图片(如图三)。

图一:

image.png

图二:会生成二外的Texture

image.png

图三:生成了额外的Texture

image.png

3.其他简单说明

3.1 使用unity默认shader,导致大量的重复shader

如下图:

image.png

解决方案:

  1. 禁止使用系统默认的shader,自己实现相应功能的shader,将shader文件放在同一AB包中。

3.2 图集的结构问题

同一图集的图片,放在不同的AB包结构下,会导致图集在不同的AB包中都存在。对内存和包体影响会比较大。

3.3 其他遇见的问题

  1. shader的变体问题: 尽量减少变体,使用Shader Variants Collection进行控制,使用代码预加载Shader Variants Collection。 不要将Shader Variants Collection放到Graphics设置中,对AB处理没有作用。对Shader.Find方法有作用。
  2. 材质球尽量和预设放在一个AB包里面。 出现过不放在一起,变体没有生效的问题。
  3. AB包最好不要超过2M,协程加载时在一些机器上可能会出现卡顿。
  4. AB包中的shader要按资源加载的方式处理,不能使用Shader.Find()。
  5. 美术对sprite怎么生成图不理解,导致特效制作时容易出问题。
  6. 图片压缩格式不正确,会导致占用额外的内存。建议android尽量使用ETC格式
  7. 美术字体问题,美术字体使用的Texture,设置成sprite导致了在图集中也会存在。

说明:以上观点仅是本人自己的观点,如有问题请联系我,我会及时更正。

基于Unity开发WebGL项目加载AB包

  在上一篇文章中我们简单介绍了unity发布webgl时如何加载AB包的方法(连接:基于Unity开发WebGL项目加载AB包(一)_梵高先森丶的博客-CSDN博客),但是上篇中讲述的是AB包放在项目的StreamingAssets文件夹中,我们都知道,在实际应用的场景中,AB包资源往往是不会放在项目里,而是需要从外部加载的。

  那么,接下来本篇文章和下一篇文章,将分别介绍WebGL如何从局域网(本地服务器)加载AB包和如何从公网(外部服务器)加载AB包。废话不多说,直接开始,还是以我们上篇文章创建的工程为例:

一、将AB包资源发布到IIS服务器:

  首先,将我们的AB包资源放到一个指定的文件夹下:

 (PC里放的时Pc端AB包资源,WEB里放的是WebGL端AB包资源)

  然后,在IIS上添加一个新的网站,物理路径选择我们刚刚存放AB包的文件夹,并绑定一个端口:

点击确定,得到我们的网站,点击浏览,发现: 

这时,我们需要把该网站的目录浏览权限打开

 

启用后重新点击浏览,可以看到:

 

 一个简化的文件夹结构,并且可以点击进入下一层目录。

我们可以尝试点击一下我们的资源,看是否可以直接下载到,然后发现报错:

 

告诉我们是因为没有添加这个格式的MIME类型,那么此时,我们需要添加对应的MIME类型(详情可以看上一篇文章),添加完成后重新尝试下载:

发现已经可以成功下载到资源啦,那也就意味着我们这一步已经成功了。

二、通过局域网加载: 

 首先我们需要另外一台同局域网的终端设备,可以是公司里与你连接同一个网络的同事的电脑,也可以是一个虚拟机。我这里为了方便经常调试,使用了虚拟机。

  在虚拟机浏览器输入你的PC的IP地址,后面加上我们刚发布的网站的地址(物理主机IP+网站端口号),尝试访问:

 发现可以正常访问,并且可以通过点击下载到我们的资源,那么我们接下来就可以尝试在项目中去加载这些资源。

修改代码(将StreamingAssets路径替换为我们的网站地址):

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;

public class LoadABTest : MonoBehaviour


    private void Start()
    
        string filePath = "";
        if (Application.platform == RuntimePlatform.WindowsEditor)
        
            //filePath = Application.streamingAssetsPath + "/PC/myabcube.unity3d";
            filePath = "http://192.1**.*.*:8050" + "/PC/myabcube.unity3d";
        
        else if (Application.platform == RuntimePlatform.WebGLPlayer)
        
            //filePath = Application.streamingAssetsPath + "/WEB/myabcube.unity3d";
            filePath = "http://192.1**.*.*:8050" + "/WEB/myabcube.unity3d";
        

        StartCoroutine(LoadModelEntity(filePath));
    


    private UnityWebRequest request;
    IEnumerator LoadModelEntity(string path)
    

        request = UnityWebRequestAssetBundle.GetAssetBundle(path);//请求资源

        yield return request.SendWebRequest();//等待完成

        AssetBundle ab = (request.downloadHandler as DownloadHandlerAssetBundle).assetBundle;//转为AB包

        if (ab != null)
        
            GameObject objModel = Instantiate(ab.LoadAsset<GameObject>("myabcube"));//实例化

            objModel.name = "MyABCubeGroup";//重命名

            ab.Unload(false);
        
        else
        
            Debug.LogError("ab=null,未加载到AB包");
        
    

修改后保存,删除掉原先StreamingAssets中的资源,并尝试在编辑器运行:

 发现资源正常加载了出来。那么我们进行下一步,将修改后的工程build,发布到IIS(详细过程见上一篇文章)。

完成发布后到虚拟机的浏览器输入网站地址(物理主机IP+网站端口号),发现并未能成功加载到资源,F12开启开发者工具可以看到有报错:

 这个报错是跨域问题报错,关于WebGL进行http请求的跨域问题解决可以看这篇文章:Unity-WebGL进行http请求的跨域问题_StubbrnStar的博客-CSDN博客_unity webgl 跨域

解决方案就是在我们的项目网站和AB包资源网站各添加4个HTTP响应标头(对应名称 值)

Access-Control-Allow-Credentials
true

Access-Control-Allow-Headers
Accept, X-Access-Token, X-Application-Name, X-Request-Sent-Time

Access-Control-Allow-Methods
GET, POST, OPTIONS

Access-Control-Allow-Origin
*

 添加完成后,我们重新在虚拟机的浏览器中打开:

 可以看到,我们的AB包资源已经成功加载出来啦。

至此,我们已经实现了从局域网加载AB包的功能,下一篇文章,我们将介绍从公网加载AB包的方法。

以上是关于Unity 项目AB资源 重复内容排查的主要内容,如果未能解决你的问题,请参考以下文章

AssetBundle Browser 教程丨Unity自带的一款AB包打包工具

AssetBundle Browser 教程丨Unity自带的一款AB包打包工具

基于Unity开发WebGL项目加载AB包

unity AB包体大小优化

unity AB包体大小优化

unity AB包体大小优化