unity AB包体大小优化

Posted 尘世喧嚣

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了unity AB包体大小优化相关的知识,希望对你有一定的参考价值。

1模型Texture 贴图优化

项目AB里面,角色的数量比较多,从而角色模型的AB体积也比较庞大,角色模型一方面要控制好顶点 三角面数量,另一方面就是模型贴图资源优化,美术做资源的时候,为了追求质量,经常会把模型贴图搞的特别大,就拿我们现在这个项目来说吧,美术用的的模型贴图都是4096*4096的,到了unity里面,肯定不能这样搞要,4096你让低端机还玩个鸟呀,所以限定了贴图 Max Size为2048。
原始的资源格式如下,一个模型里面包含3张这样格式的贴图,分别是uv贴图,法线贴图,和一张灰度贴图,打出来的AB资源是5.7M。


考虑到我们的项目是RPG 回合制游戏,角色只有在战斗场景中会存在多个,而且距离摄像机距离没有特别明显的变动,所以就建议去掉MipMap。然后打包AB,资源大小为4.1M。
接下来要处理的就是贴图压缩了,我这里主要测试了android的,由于贴图都不带透明通道,所以UV贴图和灰度贴图采用了RGBCrunchedETC格式,法线贴图采用了RGBCompressETC4bit 方式,AB资源大小为2M
如果法线贴图也按照RGBCrunchedETC方式进行压缩的话,AB资源大小可以降到1.4M,这个根据根据显示效果而定。
还有就是 Max Size的设置,最好是根据模型显示效果进行分类控制

2TimeLine 资源优化

项目战斗技能,我们采用的是TimeLine制作的,今天查看了一下TimeLine资源,一个TimeLine 的prefab资源,竟然达到了1M多,有个别的都2M了,我的天呢,你们这群美术小伙伴都对TimeLine做了啥,于是我就用AssetBundleBorswer工具分析了一下00003号角色大招的 TimeLine AB资源,不看不知道,一看吓一跳,这些都是什么鬼呀。为什么会有一堆其他角色的animation和timeline资源。

然后我看了一眼 unity 编辑器中的原始资源


资源好像也没啥毛病,那这一堆乱七八糟的资源是从哪里来的,既然AB认为他们有引用关系,那肯定还是有问题的,只能从meta文件中在进行求证了。这次倒是没有让我失望,在m_SceneBindings属性下面看到了这一堆被引用的资源,无语了。

然后回到unity,开启debug 模式,重新审视资源,怪我太年轻,不懂人心险恶,差点儿就被你蒙混过关了,这106个资源引用,打出来的AB能小吗,哎!

我实际需要的资源,只有关闭debug模式的时候,显示的这三个资源呀

我该肿么办,既然是码农,那就发挥出搬砖精神吧,度娘度娘,我要搬砖了,然后度娘给了我一个链接
https://zhuanlan.zhihu.com/p/396526134
果然是同道中人,感谢楼主帮我们趟坑,然后复制粘贴,一个修改工具就做好了

    [MenuItem("Assets/CleanUpPlayableBind")]
    private static void CleanUpPlayableBind()
    
        GameObject gob = Selection.activeGameObject as GameObject;
        if (gob != null) 
            var playable = gob.GetComponent<PlayableDirector>();
            CleanUpBind(playable);
        
    

    public static void CleanUpBind(PlayableDirector playable)
    
        if (playable == null) return;
        Dictionary<UnityEngine.Object, UnityEngine.Object> bindings = new Dictionary<UnityEngine.Object, UnityEngine.Object>();
        foreach (var pb in playable.playableAsset.outputs)
        
            var key = pb.sourceObject;
            var value = playable.GetGenericBinding(key);
            if (!bindings.ContainsKey(key) && key != null)
            
                bindings.Add(key, value);
            
        

        var dirSO = new UnityEditor.SerializedObject(playable);
        var sceneBindings = dirSO.FindProperty("m_SceneBindings");
        for (var i = sceneBindings.arraySize - 1; i >= 0; i--)
        
            var binding = sceneBindings.GetArrayElementAtIndex(i);
            var key = binding.FindPropertyRelative("key");
            if (key.objectReferenceValue == null || !bindings.ContainsKey(key.objectReferenceValue))
                sceneBindings.DeleteArrayElementAtIndex(i);
        
        dirSO.ApplyModifiedProperties();
    

搞定!顺便提一嘴,TimeLine用到的animaton资源,记得压缩它们的浮点数精度值和scale通道,通常情况下我们用不到这么高的精度,之前打AB比较大,除了多余的资源,animation也没有压缩。最终这个AB资源从1.6M,被我降低到了132k,Nice。

Animation优化

核心代码

    [MenuItem("Assets/AnimationClipChange/Directory/降低精度并删除Scale通道")]
    private static void ChangeAnimFloatAndScaleDirectory()
    
        Object gob = Selection.activeObject;
        string path = AssetDatabase.GetAssetPath(gob);
        if (Directory.Exists(path))
        
            string[] udids = AssetDatabase.FindAssets("t:AnimationClip", new string[]  path );
            int index = 0;
            foreach (var item in udids)
            
                string itemPath = AssetDatabase.GUIDToAssetPath(item);
                EditorUtility.DisplayProgressBar("执行中..." + path, itemPath, (float)index / udids.Length);

                AnimationClip clip = AssetDatabase.LoadAssetAtPath<AnimationClip>(itemPath);
                optmizeAnimationFloatAndScale(clip);
                index++;
            
            EditorUtility.ClearProgressBar();
            Debug.LogColor("AnimationClip change float finish!");
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
        
        else
        
            Debug.LogError("select target is not a directory:" + path);
        

    


    static void optmizeAnimationFloatAndScale(AnimationClip targetAnimClip)
    
        optmizeAnimationScaleCurve(targetAnimClip);
        optmizeAnimationFloat(targetAnimClip);
        Resources.UnloadUnusedAssets();
        
    


    /// <summary>
    /// 优化浮点数精度
    /// </summary>
    static AnimationClip optmizeAnimationFloat(AnimationClip clip)
    
        //浮点数精度压缩到f3
        AnimationClipCurveData[] curves = null;
        curves = AnimationUtility.GetAllCurves(clip);
        Keyframe key;
        Keyframe[] keyFrames;
        for (int ii = 0; ii < curves.Length; ++ii)
        
            AnimationClipCurveData curveDate = curves[ii];
            if (curveDate.curve == null || curveDate.curve.keys == null)
            
                //Debug.LogWarning(string.Format("AnimationClipCurveData 0 don't have curve; Animation name 1 ", curveDate, animationPath));
                continue;
            
            keyFrames = curveDate.curve.keys;
            for (int i = 0; i < keyFrames.Length; i++)
            
                key = keyFrames[i];
                key.value = float.Parse(key.value.ToString("f3"));
                key.inTangent = float.Parse(key.inTangent.ToString("f3"));
                key.outTangent = float.Parse(key.outTangent.ToString("f3"));
                keyFrames[i] = key;
            
            curveDate.curve.keys = keyFrames;
            clip.SetCurve(curveDate.path, curveDate.type, curveDate.propertyName, curveDate.curve);
        

        return clip;
    

    /// <summary>
    /// 优化scale曲线
    /// </summary>
    static AnimationClip optmizeAnimationScaleCurve(AnimationClip clip)
    
        //去除scale曲线
        foreach (EditorCurveBinding theCurveBinding in AnimationUtility.GetCurveBindings(clip))
        
            string name = theCurveBinding.propertyName.ToLower();
            if (name.Contains("scale"))
            
                AnimationUtility.SetEditorCurve(clip, theCurveBinding, null);
            
        

        return clip;
    

以上是关于unity AB包体大小优化的主要内容,如果未能解决你的问题,请参考以下文章

unity AB包体大小优化

unity AB包体大小优化

Unity纹理优化:缩小包体

Unity3D插件Build Report Tool插件,Build报告,优化包体,查看资源占用

记一次Unity极限减少包体大小

unity webgl开发踩坑——从开发发布到优化