一、问题

时常听到测试那边说打出来的包超过4G(如图,找测试要的最新的包的大小是3.84G),部分平台有包体大小限制,不能上传整包,超出部分只能打热更包。并且苹果还会有超过4G的包可能装不上的问题
因此,我想看看项目内的资源是否有可以再优化的空间,或者是否有冗余的地方

二、分析

包体过大可能是因为资源问题

image001
首先,本地打AssetBundles,然后再用最新的AssetStudio打开整个打包后的Android文件夹,如图,Android文件夹占用空间大小为4.44G
image002
然后,通过FolderSize工具看到bigimg文件夹下有300多兆,是Image文件夹下最大的。看看里面的资源能不能进行优化
image003
image004
image005
可以看到,很多资源的利用率太低,空白像素太多了。

那么,Unity在打包时会自动优化空白像素吗,为此,我创建了一个测试项目打包看看压缩后的空白像素对打包后AB包的影响:

先随意挑选几张图,将其打包设置改为RGBA Compressed ETC2 8 bits:
image006
然后写一个简单的脚本将每一个资源打一个AB包:

using UnityEditor;
using System.IO;

public class BuildAssetBundle
{
    [MenuItem("Tools/Build Image AssetBundle")]
    static void BuildImageAB()
    {
        string outputPath = "AssetBundles";
        if (!Directory.Exists(outputPath)) Directory.CreateDirectory(outputPath);
        string[] imagePaths = Directory.GetFiles("Assets/Texture", "*.png", SearchOption.AllDirectories);
        AssetBundleBuild[] builds = new AssetBundleBuild[imagePaths.Length];
        for(int i = 0;i < imagePaths.Length;i++)
        {
            string[] infos = imagePaths[i].Split(new string[] { "/", "\\" }, System.StringSplitOptions.RemoveEmptyEntries);
            string name = infos[infos.Length - 1] + ".data";
            builds[i] = new AssetBundleBuild
            {
                assetBundleName = name,
                assetNames = new string[] { imagePaths[i] }
            };
        }
        BuildAssetBundleOptions buildOptions = BuildAssetBundleOptions.StrictMode | BuildAssetBundleOptions.ChunkBasedCompression;
        buildOptions |= BuildAssetBundleOptions.ForceRebuildAssetBundle;
        BuildPipeline.BuildAssetBundles(outputPath, builds, buildOptions, BuildTarget.Android);
    }
}

打包后:
image007

在AssetStudio打开:
image008
image009

对比newbg51_1和newbg51_1_1打包出来的文件大小,可以看出,压缩后ETC2格式对空白像素是有进行压缩的

newbg51_1_1我加了个渐变,可以看到文件大小为219KB,而相同尺寸大小的newbg51_1只有55KB
image010

对比2.4_ui_wubz_bian_q、2.4_ui_wubz_bian_q_1、2.4_ui_wubz_bian_q_2三张图(上图从左到右)打包出来的文件大小,可以看出,压缩后ETC2格式对空白像素和相同像素都是有进行压缩的,甚至白色背景的图压缩得更小

去掉空白像素后,比原来的更小(2.4_ui_wubz_bian_q打包后是55KB,2.4_ui_wubz_bian_q_2打包后是39KB)

可以得出:优化空白像素能优化一点包体大小,并且运行时加载资源后所占用的内存也会缩小一点

再试试RGB(A) Compressed ASTC 6*6 block格式:

image011

打包后:
image012

在AssetStudio打开:

image013
首先可以看出,打出来的Bundle大小大了一点

其次,ASTC格式也会压缩空白像素和相同像素,并且去掉空白像素也能优化一点包体大小

第三,对比在AssetStudio打开的情况可以看出,ASTC虽然打出来的包会比ETC2大一点,但是ASTC解压后的大小会比ETC2小很多,平均小50%以上,对运行时的内存比较友好

包体过大也可能是资源重复打包的问题

包体太大还有可能是资源重复打包问题,所以我本地打的AB包导入到AssetStudio中:
image014
可以看出,其实冗余资源还是挺多的

项目中其实已经有通用的资源库

那么小试一下将资源移动到通用资源库中,是否能缩小包体大小:

这里以上图中的mask为例,这个资源应该是用于圆形遮罩,资源是打进图集的,但是看了一下,项目中有一个UIMask的组件,是直接引用Texture2D的,所以有使用到这个组件并且用了这张图的地方,都用会重复打包

我复制了一个mask资源到通用资源库,并在本地写了个简单的工具判断UIMask组件是否引用到这个资源,若是则将引用修改为通用资源库的资源,并保存修改,工具代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class SetUIMask
{
    private static List<string> allPrefabs = null;
    private static Texture2D mask;
    private static bool isRunning = false;
    private static IEnumerator asyncTask;

    [MenuItem("Tools/一键修改被UIMask引用到的mask遮罩")]
    public static void SetUIMask_mask()
    {
        string path = "Assets/GameAssets/prefabs/";
        allPrefabs = CommonFunction.GetAllFilesInDirectory(path, "*.prefab");
        mask = AssetDatabase.LoadAssetAtPath<Texture2D>("Assets/GameAssets/bundleres/common/texture/mask.png");
        isRunning = !isRunning;
        if (isRunning)
        {
            Debug.LogError("开始运行");
        }
        else
        {
            Debug.LogError("暂停运行");
        }
        asyncTask = AsyncTask();
        EditorApplication.update += OnUpdate;
    }

    public static void OnUpdate()
    {
        if (isRunning)
        {
            bool succ = asyncTask.MoveNext();
            if (!succ)
            {
                isRunning = false;
                EditorApplication.update -= OnUpdate;
            }
        }
    }

    private static IEnumerator AsyncTask()
    {
        for (int i = 0; i < allPrefabs.Count; i++)
        {
            string prefabPath = allPrefabs[i];
            GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
            UIMask[] uimasks = prefab.GetComponentsInChildren<UIMask>(true);
            bool isChanged = false;
            for (int j = 0; j < uimasks.Length; j++)
            {
                if (uimasks[j].MaskTexture != null)
                {
                    string tex_path = AssetDatabase.GetAssetPath(uimasks[j].MaskTexture);
                    if (tex_path.Equals("Assets/AtlasSource/skinlib/mask.png"))
                    {
                        isChanged = true;
                        uimasks[j].MaskTexture = mask;
                    }
                }
            }
            if (isChanged)
            {
                PrefabUtility.SavePrefabAsset(prefab);
            }
            yield return null; // 每帧执行一次
        }
        AssetDatabase.Refresh();
    }
}

(这里的工具逻辑还加了异步,并且支持停止)

我将 Assets/GameAssets/prefabs/ 和 Assets/GameAssets/ui/ 两个路径下的预制资源符合上述UIMask组件引用的都改了

再次打包发现,引用数并没有变少(没图,后面又改了打包了覆盖之前的了)

我看重复打包的很多都是特效的资源,怀疑是资源格式的问题,并且通用资源库文件夹下的贴图资源,有两种格式,Default和Sprite,在AssetStudio上搜了一下,发现格式为Default的资源没有被重复打包

而格式为Sprite的资源即使在通用资源库打包一次的情况下,还是会重复打包,并且这些资源很多都是材质球在引用,所以估计是材质球引用Sprite格式的Texture资源会导致重复打包

在测试项目中验证一下(Unity版本2020.3.32f1):
image015
image016
image017
image018
image019
随便弄一张图,改成Sprite格式,创建5个材质球,并且创建8个预制,其中预制1和预制2如上图嵌套引用,预制3到8都是相同的(同上图预制4)

然后修改打包逻辑,把全部材质球和预制都逐个打AB包:
image020
image021
image022

打包后可以看出,lightning_b_01被重复打包了,但是这个资源本来也会打包,这里就有问题

继续,修改打包逻辑,将全部材质球打成一个包:
image023

image024

image025

将全部材质球打成一个包之后,发现重复打包次数变少了,但是lightning_b_01的Texture还是打了两次

继续,将资源格式改成Default,打包:

image026

image027

image028

image029

可以看出,lightning_b_01没有重复打包了

继续,打包逻辑改回一个材质球打一个包:

image030

image031

image032

可以看出,lightning_b_01同样没有重复打包了

在Unity2022.3.62f2c1的版本上试了一下,材质球引用Sprite格式·的资源还是会有这个问题

image033

综上,得出结论,材质球引用的纹理图需要是Default格式,如果是Sprite格式,除非这些引用到同一资源的材质球打成一个包,否则就会重复打包

并且,Sprite格式解压后会多一个Sprite的资源,如果没用的话,也会占用运行时的内存

那么,为什么有的特效资源被材质球引用,但格式却是Sprite呢?

我记得是Unity编辑器有一个设置的,找了半天,终于找到了:
image034

这个参数设置为2D的时候,导入的资源默认为Sprite格式,设置为3D的时候,导入的资源默认为Default格式



大佬们发现有错误欢迎拍砖~

 posted on 2025-12-30 11:20  chj一诺千金  阅读(9)  评论(0)    收藏  举报