前两天有朋友告诉我Unity的Assetbundle是LZMA压缩的,刚好今天有时间那么就研究研究LZMA。它是一个开源的类库,有C、 C++、C#、JAVA的类库,那么在我大Unity里面我们当然要使用C#的类库啦。
下载地址:http://www.7-zip.org/sdk.html 或者在文章的最后下载我的测试工程、如下图所示,因为9.22是Beta版本,所以我们还是老老实实下载9.20正式版本。
解压后把整个CS文件夹拖入Unity工程即可。当我在拖入Unity的时候发现Settings.cs报错了,查了一下是因为mono并不是完整的.net 。不过这个文件我们不需要用,所以直接把Settings.cs删除即可。
下面上代码,这是编辑时的一个类。我先把根目录下的一个文件压缩,接着在解压缩。
using UnityEngine;
using System.Collections;
using UnityEditor;
using SevenZip.Compression.LZMA;
using System.IO;
using System;
public class Test : Editor {
[MenuItem ("MyMenu/CompressFile")]
static void CompressFile ()
{
//压缩文件
CompressFileLZMA(Application.dataPath+"/1.jpg",Application.dataPath+"/2.zip");
AssetDatabase.Refresh();
}
[MenuItem ("MyMenu/DecompressFile")]
static void DecompressFile ()
{
//解压文件
DecompressFileLZMA(Application.dataPath+"/2.zip",Application.dataPath+"/3.jpg");
AssetDatabase.Refresh();
}
private static void CompressFileLZMA(string inFile, string outFile)
{
SevenZip.Compression.LZMA.Encoder coder = new SevenZip.Compression.LZMA.Encoder();
FileStream input = new FileStream(inFile, FileMode.Open);
FileStream output = new FileStream(outFile, FileMode.Create);
// Write the encoder properties
coder.WriteCoderProperties(output);
// Write the decompressed file size.
output.Write(BitConverter.GetBytes(input.Length), 0, 8);
// Encode the file.
coder.Code(input, output, input.Length, -1, null);
output.Flush();
output.Close();
input.Close();
}
private static void DecompressFileLZMA(string inFile, string outFile)
{
SevenZip.Compression.LZMA.Decoder coder = new SevenZip.Compression.LZMA.Decoder();
FileStream input = new FileStream(inFile, FileMode.Open);
FileStream output = new FileStream(outFile, FileMode.Create);
// Read the decoder properties
byte[] properties = new byte[5];
input.Read(properties, 0, 5);
// Read in the decompress file size.
byte [] fileLengthBytes = new byte[8];
input.Read(fileLengthBytes, 0, 8);
long fileLength = BitConverter.ToInt64(fileLengthBytes, 0);
// Decompress the file.
coder.SetDecoderProperties(properties);
coder.Code(input, output, input.Length, fileLength, null);
output.Flush();
output.Close();
input.Close();
}
}
我参考了这篇文章,不过它点问题,所以我改了改。
http://stackoverflow.com/questions/7646328/how-to-use-the-7z-sdk-to-compress-and-decompress-a-file
如下图所示,我把1.jpg先压缩成2.zip ,然后在把2.zip在解压成3.jpg。
下载地址:http://pan.baidu.com/s/1dDBxyBv
如果你想运行时运行LZMA按照上述代码简单改改就可以使用了。比如你把压缩过的文件放在服务器,然后用www下载到内存以后,可以通过lzma的解压方法将文件还原在保存在本地。 欢迎大家一起讨论与学习。嘿嘿,或者有什么更好的压缩方式,欢迎在下面给我留言,谢谢。
- 本文固定链接: https://www.xuanyusong.com/archives/3095
- 转载请注明: 雨松MOMO于 雨松MOMO程序研究院 发表
捐 赠写博客不易,如果您想请我喝一杯星巴克的话?就进来看吧!




我先打包一个预制,然后用你的方法压缩,解压,再加载解压出来的.unity3d文件,但加载不了,错误:ArgumentException: The thing you want to instantiate is null.
大神,我参考您写的文章,用LMZA压缩了一个打包好的未压缩的场景(参考您的Assetbundle文章),然后用CreateFromFile读取的时候,他还是按压缩的场景读取,结果报错说不能用压缩的场景,不知为何。。。。而且我用winRAR软件试图打开LMZA压缩的文件,结果说这个文件格式未知或数据已损坏(保存的格式为.zip)。。。。求指点
是我打包的Editor类写错了个后缀。。。。
问下 怎么判断这个文件已经解压过了? 解压已经解压过的文件, 就会产生OutOfMemory异常导致闪退.
要给地方存文件的大小。 比如cdn上
你好怎么实现异步解压
我也想知道怎么异步啊,一个文件解压要等好久,又没有提示
你好我用了你的方法压缩txt文件,unity 4.6.3 在64位windows和mac下都能正常解压,唯独用touch同步调试的时候,显示access to the path “解压文件路径” is denied网上搜到的都是纯windows下的解决方法,mac下也已经给了所有用户读和写权限,还是没能解决
只能一个个文件压缩吗,能不能把一个文件夹一次性整体压缩?
同求解决方法。。。
请问如何在压缩的时候添加密码?
没法加密码, 可以 把加密完的assetbundle 转成 字节流 然后在打成assetbudle 。。。 下载完的时候 同样方法解密就可以了。
在移动平台上我先使用LZF再使用LZMA压缩,对于文本和二进制文件压缩率和压缩/解压时间都有较大的改善。
正解
请问下这个与楼主先前的7ZIP比效率如何
还有就是不明白为什么不在打包的时候让unity自己就压缩好呢?不是默认的打包是可以压缩的吗?
MOMO大大,我发现如果有多个需要打包的assetbundle,分别打包的后的总大小比打在一起的总大小要大,而且需要打包的数量越多就越明显,一个项目里要打包的资源是不可能很少的,那么是不是全部打在一起呢?
用C#来写。。
赞!
雨大大,我试了下将压缩打包的assetbundle再压缩成zip,发现压缩前和压缩后大小一点没变,是不是因为assetbundle已经压缩过了,无法再压缩了啊。
BuildAssetBundleOptions.UncompressedAssetBundle | BuildAssetBundleOptions.CollectDependencies 用这个参数。默认assetbundle就已经 lzma压缩了。
问一下,我用这个压缩把7z.dll和SevenZipSharp.dll放在Plugins目录下,然后使用 SevenZipCompressor tmp = new SevenZipCompressor();tmp.ArchiveFormat = OutArchiveFormat.Zip;tmp.CompressFiles(@”D:test.zip”, @”D:test.txt”);如下代码压缩,运行unity就自动崩掉了,请问一下又碰到这样的情况吗?成功的方法又是怎么写的?
求分享一下怎么实现。。
我在安卓上用LZMA解压.zip文件并写入本地总是失败,怎么回事呢?在PC上是可以解压的,我的代码如下private static void DecompressFileLZMA(Stream input, string outFile) { SevenZip.Compression.LZMA.Decoder coder = new SevenZip.Compression.LZMA.Decoder(); FileStream output = new FileStream(outFile, FileMode.Create); // Read the decoder properties byte[] properties = new byte
; input.Read(properties, 0, 5); // Read in the decompress file size. byte[] fileLengthBytes = new byte
; input.Read(fileLengthBytes, 0, 8); long fileLength = BitConverter.ToInt64(fileLengthBytes, 0); // Decompress the file. coder.SetDecoderProperties(properties); coder.Code(input, output, input.Length, fileLength, null); output.Flush(); output.Close(); input.Close(); }outFile = string.Format(“{0}/{1}.assetbundle”, Application.persistentDataPath, myAssetBundle.FileName)运行时路径是:”/storage/sdcard0/Android/data/xxxxx/files/xxxxx.assetbundle”求大神解惑
看看本地有空间没?
我在服务器端压缩了www.text,在客户端如何解压啊?
多个压到一个,怎么压,怎么解压。。。这是个问题
DecompressFileLZMA(string inFile, string outFile) 中的 参数 inFile 怎么和www下载下来的文件 联系起来呢?
就是你另一篇文章中写的3.解压缩这些assetbundle并且保存在Application.persistentDataPath 目录下。4.以后通过AssetBundle.CreatFromFile 读取assetbundle。不知道怎么实现
FileStream fs = File.Create(path + img_name); //path为你想保存文件的路径。 fs.Write(www.bytes, 0, http://www.bytes.Length); fs.Close();
FileStream fs = File.Create(path img_name); //path为你想保存文件的路径。 fs.Write(www.bytes, 0, http://www.bytes.Length); fs.Close();
用了这个就用不着ab了吧? 我要更新的都是图片.压缩好放服务器.然后下载了直接解压就是替换老的图片了吧?
不是, 我们用这个来自己压缩 assetbundle.这样就可以用creatfromefile 来同步加载assetbundle
谢了.
哈哈,最近在做更新,发现打出的ab非常大,用了这个压缩,缩小了10倍左右,开心开心,哈哈
lzma压缩是小了 但是解压的时间就长了。。 呵呵
我是在看了您的Unity3D研究院之Assetbundle的实战(六十三)这篇博文的下面补充,才想到的对资源进行压缩,用了一些别的压缩方法竟然都没成功。就学习了您的,我们最近也想做资源更新,我发现我即使用依赖打包的那种方式,会把资源包搞得很大,,这样在手机Application.persistentDataPath目录下面显得数据非常大(我试的安卓机),玩家一清除数据就啥也没了,就想到了写到手机的固定存储位置,这样就是从固定位置读取了,下载包小一点可以节省玩家流量。哈哈,就压缩,就想着程序在把资源更新下来后顺便解压还原,在游戏中运行了后采用选择性加载。说了这么多,您这么一说,解压时间长,哎,就说明我的思路又有问题了,坑啊
,
13m 用了90秒 ipod 5
麻烦问下。如何缩小10倍。我测试过发现,压缩前和压缩后基本没什么变化呢。。
考虑这个能不能做增量。然后我把多个文件压到一起,请问大大解压的时候怎么获取里面文件的名字??
压缩效果好像不是那么明显哈