之前提到过通过AssetBundle.CreateFromFile读取本地AssetBundle,因为该方法只能读取未压缩的AssetBundle,所以打包AssetBundle时,需要选择BuildAssetBundleOptions.UncompressedAssetBundle未压缩模式,然后使用LZMA或GZIP压缩后上传服务器。本地下载后需要解压缩保存在Application.persistentDataPath目录下。

下面说明如何压缩AssetBundle。

首先需要下载7-zip的C#核心文件,下载地址http://www.7-zip.org/sdk.html

Unity3d热更新(四):压缩文件_下载地址

解压后将CS文件夹下的7zip文件夹导入Unity工程,下面是一个Demo,可以直接用。

[csharp] view plaincopyUnity3d热更新(四):压缩文件_服务器_02Unity3d热更新(四):压缩文件_下载地址_03

  1. using UnityEngine;  

  2. using System.Collections;  

  3. using UnityEditor;  

  4. using SevenZip.Compression.LZMA;  

  5. using System.IO;  

  6. using System;  

  7.   

  8. // 压缩或解压文件  

  9. public class CompressAndDecompress : Editor {  

  10.   

  11.     // 压缩Unity3D文件  

  12.     [MenuItem("Compress/Compress Unity3D File")]  

  13.     static void CompressUnity3DFile()  

  14.     {  

  15.         string path = EditorUtility.OpenFilePanel("Compress file""""unity3d");  

  16.         CompressFile(path);  

  17.     }  

  18.   

  19.     // 压缩Lua文件  

  20.     [MenuItem("Compress/Compress Lua File")]  

  21.     static void CompressLuaFile()  

  22.     {  

  23.         string path = EditorUtility.OpenFilePanel("Compress file""""lua");  

  24.         CompressFile(path);  

  25.     }  

  26.   

  27.     // 压缩文件  

  28.     static void CompressFile(string path)  

  29.     {  

  30.         if (path.Length != 0)  

  31.         {  

  32.             int lastDotIndex = path.LastIndexOf(".");  

  33.             string outputPath = path.Substring(0, lastDotIndex + 1) + "zip";  

  34.             CompressFileLZMA(path, outputPath);  

  35.             AssetDatabase.Refresh();  

  36.             EditorUtility.DisplayDialog("压缩文件""文件已压缩完成""确认");  

  37.         }  

  38.     }  

  39.   

  40.     // 解压Unity3D文件  

  41.     [MenuItem("Compress/Decompress Unity3D File")]  

  42.     static void DecompressUnity3DFile()  

  43.     {  

  44.         DecompressFile("unity3d");  

  45.     }  

  46.   

  47.     // 解压Lua文件  

  48.     [MenuItem("Compress/Decompress Lua File")]  

  49.     static void DecompressLuaFile()  

  50.     {  

  51.         DecompressFile("lua");  

  52.     }  

  53.   

  54.     static void DecompressFile(string extension)  

  55.     {  

  56.         string path = EditorUtility.OpenFilePanel("Decompress file""""zip");  

  57.   

  58.         if (path.Length != 0)  

  59.         {  

  60.             int lastDotIndex = path.LastIndexOf(".");  

  61.             string outputPath = path.Substring(0, lastDotIndex + 1) + extension;  

  62.             DecompressFileLZMA(path, outputPath);  

  63.             AssetDatabase.Refresh();  

  64.             EditorUtility.DisplayDialog("解压文件""文件已解压完成""确认");  

  65.         }  

  66.     }  

  67.   

  68.     // 压缩文件夹中的文件  

  69.     [MenuItem("Compress/Compress Files In Directory")]  

  70.     static void CompressFilesInDirectory()  

  71.     {  

  72.         string path = EditorUtility.OpenFolderPanel("Compress Files In Directory""""");  

  73.   

  74.         if (path.Length != 0)  

  75.         {  

  76.             DirectoryInfo source = new DirectoryInfo(path);  

  77.             DirectoryInfo target = new DirectoryInfo(path + "_compress");  

  78.   

  79.             if (target.Exists)  

  80.             {  

  81.                 target.Delete(true);  

  82.             }  

  83.   

  84.             target.Create();  

  85.             target.Refresh();  

  86.   

  87.             // 复制源文件夹到目标文件夹  

  88.             CopyAll(source, target);  

  89.             ListFiles((FileSystemInfo)target, true);  

  90.             EditorUtility.DisplayDialog("压缩文件夹""文件夹中所有的文件已压缩完成""确认");  

  91.         }  

  92.     }  

  93.   

  94.     // 解压文件夹中的文件  

  95.     //[MenuItem("Compress/Decompress Files In Directory")]  

  96.     static void DecompressFilesInDirectory()  

  97.     {  

  98.         string path = EditorUtility.OpenFolderPanel("Decompress Files In Directory""""");  

  99.   

  100.         if (path.Length != 0)  

  101.         {  

  102.             DirectoryInfo source = new DirectoryInfo(path);  

  103.             DirectoryInfo target = new DirectoryInfo(path + "_decompress");  

  104.   

  105.             if (target.Exists)  

  106.             {  

  107.                 target.Delete(true);  

  108.             }  

  109.   

  110.             target.Create();  

  111.             target.Refresh();  

  112.   

  113.             // 复制源文件夹到目标文件夹  

  114.             CopyAll(source, target);  

  115.             ListFiles(target, false);  

  116.             EditorUtility.DisplayDialog("解压文件夹""文件夹中所有的文件已解压完成""确认");  

  117.         }  

  118.     }  

  119.   

  120.     // 使用LZMA算法压缩文件  

  121.     private static void CompressFileLZMA(string inFile, string outFile)  

  122.     {  

  123.         Encoder coder = new Encoder();  

  124.         FileStream input = new FileStream(inFile, FileMode.Open);  

  125.         FileStream output = new FileStream(outFile, FileMode.Create);  

  126.   

  127.         coder.WriteCoderProperties(output);  

  128.   

  129.         byte[] data = BitConverter.GetBytes(input.Length);  

  130.   

  131.         output.Write(data, 0, data.Length);  

  132.   

  133.         coder.Code(input, output, input.Length, -1, null);  

  134.         output.Flush();  

  135.         output.Close();  

  136.         input.Close();  

  137.     }  

  138.   

  139.     // 使用LZMA算法解压文件  

  140.     private static void DecompressFileLZMA(string inFile, string outFile)  

  141.     {  

  142.         Decoder coder = new Decoder();  

  143.         FileStream input = new FileStream(inFile, FileMode.Open);  

  144.         FileStream output = new FileStream(outFile, FileMode.Create);  

  145.   

  146.         byte[] properties = new byte[5];  

  147.         input.Read(properties, 0, 5);  

  148.   

  149.         byte[] fileLengthBytes = new byte[8];  

  150.         input.Read(fileLengthBytes, 0, 8);  

  151.         long fileLength = BitConverter.ToInt64(fileLengthBytes, 0);  

  152.   

  153.         coder.SetDecoderProperties(properties);  

  154.         coder.Code(input, output, input.Length, fileLength, null);  

  155.         output.Flush();  

  156.         output.Close();  

  157.         input.Close();  

  158.     }  

  159.   

  160.     // 复制源文件夹到目标文件夹  

  161.     public static void CopyAll(DirectoryInfo source, DirectoryInfo target, ArrayList extensions = null)  

  162.     {  

  163.         if (source.FullName.ToLower() == target.FullName.ToLower())  

  164.         {  

  165.             return;  

  166.         }  

  167.   

  168.         // 检测目标文件是否存在,如果不存在,则创建  

  169.         if (!Directory.Exists(target.FullName))  

  170.         {  

  171.             Directory.CreateDirectory(target.FullName);  

  172.             target.Refresh();  

  173.         }  

  174.   

  175.         // 复制文件至目标文件夹  

  176.         foreach (FileInfo fi in source.GetFiles())  

  177.         {  

  178.             if (extensions == null || extensions.Count == 0)  

  179.             {  

  180.                 if (fi.Extension != ".meta")  

  181.                 {  

  182.                     fi.CopyTo(Path.Combine(target.ToString(), fi.Name), true);  

  183.                 }  

  184.             }  

  185.             else  

  186.             {  

  187.                 if (extensions.Contains(fi.Extension))  

  188.                 {  

  189.                     fi.CopyTo(Path.Combine(target.ToString(), fi.Name), true);  

  190.                 }  

  191.             }  

  192.               

  193.         }  

  194.   

  195.         // 使用递归复制子文件夹  

  196.         foreach (DirectoryInfo sourceSubDir in source.GetDirectories())  

  197.         {  

  198.             DirectoryInfo targetSubDir = target.CreateSubdirectory(sourceSubDir.Name);  

  199.             CopyAll(sourceSubDir, targetSubDir, extensions);  

  200.         }  

  201.     }  

  202.   

  203.     // 遍历文件夹中的所有文件,压缩或解压缩  

  204.     public static void ListFiles(FileSystemInfo info, bool isCompress)  

  205.     {  

  206.         if (!info.Exists)  

  207.         {  

  208.             return;  

  209.         }  

  210.   

  211.         DirectoryInfo dir = info as DirectoryInfo;  

  212.   

  213.         // 不是目录  

  214.         if (dir == null)  

  215.         {  

  216.             return;  

  217.         }  

  218.   

  219.         FileSystemInfo[] files = dir.GetFileSystemInfos();  

  220.   

  221.         for (int i = 0; i < files.Length; i++)  

  222.         {  

  223.             FileInfo file = files[i] as FileInfo;  

  224.   

  225.             // 是文件  

  226.             if (file != null)  

  227.             {  

  228.                 string fullName = file.FullName;  

  229.   

  230.                 // 如果是压缩文件  

  231.                 if (isCompress)  

  232.                 {  

  233.                     if (file.Extension == ".unity3d" || file.Extension == ".lua")  

  234.                     {  

  235.                         string outputPath = file.FullName.Replace(file.Extension, ".zip");  

  236.                         CompressFileLZMA(fullName, outputPath);  

  237.                         File.Delete(fullName);  

  238.                     }  

  239.                 }  

  240.                 // 如果是解压文件  

  241.                 else  

  242.                 {  

  243.                     if (file.Extension == ".zip")  

  244.                     {  

  245.                         string outputPath = file.FullName.Replace(file.Extension, ".unity3d");  

  246.                         DecompressFileLZMA(fullName, outputPath);  

  247.                         File.Delete(fullName);  

  248.                     }  

  249.                 }  

  250.   

  251.             }  

  252.             else  

  253.             {  

  254.                 ListFiles(files[i], isCompress);  

  255.             }  

  256.         }  

  257.     }  

  258. }