这篇总结主要是总结下资源的热更新

前段时间闲来无事,狂撸了下项目的热更新代码,写个笔记总结下吧

 

打包其实比较简单,主要是项目结构的设计和文件目录的处理比较麻烦。

先设计一个文件结构

--ABResource -- 所有资源打包的主目录

  //这些目录是资源的大类

  --UI -图集,图片icon资源等

    --Module1

    --Module2

    --Module3

  -Animation  动画 animator等资源

    --Module1

    --Module2

    --Module3

  --Sound  声音资源

    --Module1

    --Module2

    --Module3

  --Model  模型资源

  --Map    地图资源,场景相关的超级大图

  --Effect  特效类

  --Audio    视频类

 

  文件结构的设计直接影响后期的开发效率,打包方式流程其实都知道,但是文件目录结构设计的好,对项目的开发效率提升非常大,所有模块对应的子文件夹名字尽量统一,方便开发的时候使用统一命名存取资源。减少逻辑成本!

  打包唯一复杂的地方就是文件夹读取,后缀名的转换

  关键是对这个结构体字段的理解 AssetBundleBuild

  首先,每一个AssetBundleBuild都代表将要生成的一个ab文件

  一个ab文件里面可以关联N个资源,至于多少个资源,由AssetBundleBuild里面的assetNames决定,Unity会根据名字找到当前这个文件夹里面的资源,注意这里面的路径都是Unity Asset开始的相对路径,而C#的Path、Directory这些路径获取工具拿到的都是全局路径,需要自己做转换

  

AssetBundleBuild里面只有2个字段是比较重要的

 AssetBundleBuild.assetBundleName  --------这个字段决定了你这份ab文件生成的名字

AssetBundleBuild.assetNames            --------这个字段决定了你这份ab文件里面包含了多少个资源

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using UnityEditor;
using System.Linq;
using System;
public class BundelTest  {

   private static Dictionary<string,AssetBundleBuild> modulAbDic = new Dictionary<string, AssetBundleBuild>();
   Dictionary<string,AssetBundle> AllAb = new Dictionary<string, AssetBundle>();
   /// <summary>
   /// 解析每个模块
   /// </summary>
   /// <param name="path"></param>
   public static void BuildAllBundle(string path)
   {
    //这里是采用上述的文件结构,所以做的3层遍历,也可以做成递归的方式,让其适用多个层级
      // 判断这个路径是否存在
      if (Directory.Exists(path)) 
      {
          Directory.CreateDirectory(path);
      }
      string realPath  = Path.Combine(Application.dataPath,path);
      string[] floderList =   Directory.GetDirectories(realPath);//这个只能获取当前层级的子层级,不能获取嵌套的

   
      for (int i = 0; i < floderList.Length; i++)
      {
        
        string[] fileNames =   Directory.GetDirectories(floderList[i]);//这个文件夹下的所有的子文件夹     
        for (int a = 0; a < fileNames.Length; a++)
        {
            getBundls(fileNames[a]);//第一层文件夹下面的文件。不包括里面文件夹
        }
      }
   }




    /// <summary>
    /// 解析模块内的资源
    /// </summary>
    /// <param name="path"></param>
   public static void getBundls(string modulePath)
   {
        modulePath = modulePath.Replace("\\","/"); //合并的路径都是\\需要转义
       
        string[] flies =  Directory.GetFiles(modulePath);
    
        if  (flies.Length > 0 )
        {
           for (int i = 0; i < flies.Length; i++)
           {
               //处理模块内文件
               string assetBundleName  = flies[i].Replace(Application.dataPath+"/","");
                string ralativePath = getRelativePah(flies[i]);
                string _abPath =ralativePath;
                string ext =  Path.GetExtension(ralativePath);
                assetBundleName = assetBundleName.Replace(ext,"")+".ab";
                if (ext != ".meta")
                {
                    string name = Path.GetDirectoryName(ralativePath)+"/"+Path.GetFileNameWithoutExtension(ralativePath); //包的名字,这个名字包含了资源的路径。
                    AssetBundleBuild build = new AssetBundleBuild() ;
                    if (modulAbDic.ContainsKey(_abPath))
                    {
                        if (modulAbDic.TryGetValue(_abPath,out build))
                        {
                            build.assetBundleName = assetBundleName;
                            build.assetNames = new string[]{ralativePath}; --这里是一个资源对应一个build 所以是固定的
                            modulAbDic[_abPath] = build;
                        }
                    }
                    else
                    {
                        build.assetBundleName = assetBundleName;
                        build.assetNames = new string[]{ralativePath};
                        modulAbDic.Add(_abPath,build);
                    }
                }
           }
        }
       
    }
    
    
    /// <summary>
    /// 打包所有资源,每个资源打一份ab,方便进行差异化分析
    /// </summary>
    public static  void BuildAssetBundleForDic()
    {
        AssetBundleBuild[] builds = modulAbDic.Values.ToArray();
      //输出路径可以自行选择,这里是默认输出在桌面
        BuildPipeline.BuildAssetBundles(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory),"bundle"),builds,BuildAssetBundleOptions.DeterministicAssetBundle ,BuildTarget.StandaloneWindows64);
    }

    /// <summary>
    /// 获取asset下的相对位置
    /// </summary>
    public static string getRelativePah(string path)
    {
        string _path =   path.Replace("\\","/");
        return _path.Replace(Application.dataPath,"Assets");
    }
}