游戏

游戏人生

Unity3d-AssetBundle基本格式分析

参考disunity 和云风的分析写的C#版本的 AssetBundle基本格式分析工具:https://github.com/chenanbao/AssetBundleReader


AssertBundle文件头: 

        public void Read(ByteArray bs)
        {
            signature = bs.ReadStringNull();
            streamVersion = bs.ReadInt();
            unityVersion = bs.ReadStringNull();
            unityRevision = bs.ReadStringNull();
            minimumStreamedBytes = bs.ReadInt();
            headerSize = bs.ReadUInt();

            numberOfLevelsToDownload = bs.ReadInt();
            int numberOfLevels = bs.ReadInt();

            for (int i = 0; i < numberOfLevels; i++)
            {
                levelByteEnd.Add(new LevelInfo() { PackSize = bs.ReadUInt(), UncompressedSize = bs.ReadUInt() });
            }

            if (streamVersion >= 2)
            {
                completeFileSize = bs.ReadUInt();
            }

            if (streamVersion >= 3)
            {
                dataHeaderSize = bs.ReadUInt();
            }

            bs.ReadByte();
        }

AssetBundle具体数据使用LZMA压缩(开源库:http://www.7-zip.org/sdk.html):

                SevenZip.Compression.LZMA.Decoder coder = new SevenZip.Compression.LZMA.Decoder();

                uint length = (uint) (fs.Length - header.GetHeaderSize());
                byte[] inBytes = new byte[length];
                inData.ReadBytes(inBytes, 0, length);
                MemoryStream input = new MemoryStream(inBytes);
                MemoryStream output = new MemoryStream();

                // 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);

                coder.SetDecoderProperties(properties);
                coder.Code(input, output, input.Length, fileLength, null);
                output.Position = 0;

解压后的数据格式如下,一般只包含一个Asset:

            
            uint files = inData.ReadUInt();
            Debug.Log(files);
            for (int i = 0; i < files; i++)
            {
                AssetBundleEntryInfo entryInfo = new AssetBundleEntryInfo();
                entryInfo.Read(inData);
                entryInfos.Add(entryInfo);
                Debug.Log("AssetBundleEntryInfo");

                inData.Postion = (int)entryInfo.GetOffset();
                AssetHeader assetHeader = new AssetHeader();
                assetHeader.Read(inData);
                Debug.Log("AssetHeader");

                MetadataInfo metadataInfo = new MetadataInfo();
                metadataInfo.Read(inData, assetHeader);
                Debug.Log("MetadataInfo");

                //后面的都是小端读取
                inData.IsBigEndian = false;

                ObjectInfoTable objectInfoTable = new ObjectInfoTable();
                objectInfoTable.Read(inData);
                Debug.Log("ObjectInfoTable");

                FileIdentifierTable fileIdentifierTable = new FileIdentifierTable();
                fileIdentifierTable.Read(inData, assetHeader);
                Debug.Log("FileIdentifierTable");
            }

其中ObjectInfo的classID含义可参见:http://docs.unity3d.com/Documentation/Manual/ClassIDReference.html



阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cabxyz/article/details/44940923
文章标签: 数据 开源 c#
个人分类: unity3d c#
所属专栏: Unity3d语言基础
想对作者说点什么? 我来说一句

应聘书的基本格式和写作要求

2009年07月04日 24KB 下载

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭