Example #1
0
        /// <summary>
        /// 动画控制器比较特殊,不能通过序列化得到
        /// </summary>
        /// <param name="info"></param>
        /// <param name="o"></param>
        private static void AnalyzeObjectReference2(AssetBundleFileInfo info, Object o)
        {
            AnimatorController ac = o as AnimatorController;

            if (ac)
            {
#if UNITY_5 || UNITY_5_3_OR_NEWER
                foreach (var clip in ac.animationClips)
                {
                    AnalyzeObjectReference(info, clip);
                }
#else
                List <State> list = new List <State>();
                for (int i = 0; i < ac.layerCount; i++)
                {
                    AnimatorControllerLayer layer = ac.GetLayer(i);
                    list.AddRange(AnimatorStateMachine_StatesRecursive(layer.stateMachine));
                }
                foreach (State state in list)
                {
                    var clip = state.GetMotion() as AnimationClip;
                    if (clip)
                    {
                        AnalyzeObjectReference(info, clip);
                    }
                }
#endif
            }
        }
Example #2
0
        /// <summary>
        /// 分析对象的引用
        /// </summary>
        /// <param name="assetBundleFileInfo"></param>
        /// <param name="obj"></param>
        public static void AnalyzeObjectReference(AssetBundleFileInfo assetBundleFileInfo, Object obj)
        {
            if (obj == null || assetBundleFileInfo.objDict.ContainsKey(obj))
            {
                return;
            }

            var serializedObject = new SerializedObject(obj);

            assetBundleFileInfo.objDict.Add(obj, serializedObject);

            if (s_InspectorMode == null)
            {
                s_InspectorMode = typeof(SerializedObject).GetProperty("inspectorMode", BindingFlags.NonPublic | BindingFlags.Instance);
            }
            s_InspectorMode.SetValue(serializedObject, InspectorMode.Debug, null);

            var it = serializedObject.GetIterator();

            while (it.NextVisible(true))
            {
                if (it.propertyType == SerializedPropertyType.ObjectReference && it.objectReferenceValue != null)
                {
                    AnalyzeObjectReference(assetBundleFileInfo, it.objectReferenceValue);
                }
            }

            // 只能用另一种方式获取的引用
            AnalyzeObjectReference2(assetBundleFileInfo, obj);
        }
Example #3
0
        /// <summary>
        /// 直接递归所有文件
        /// </summary>
        /// <param name="directoryPath"></param>
        /// <returns></returns>
        private static List <AssetBundleFileInfo> AnalyzAllFiles(string directoryPath)
        {
            List <AssetBundleFileInfo> infos = new List <AssetBundleFileInfo>();
            string bom = "Unity";

            char[]   flag  = new char[5];
            string[] files = Directory.GetFiles(directoryPath, "*", SearchOption.AllDirectories);
            foreach (var file in files)
            {
                using (StreamReader streamReader = new StreamReader(file))
                {
                    if (streamReader.Read(flag, 0, flag.Length) == flag.Length && new string(flag) == bom)
                    {
                        AssetBundleFileInfo info = new AssetBundleFileInfo
                        {
                            name          = file.Substring(directoryPath.Length + 1),
                            path          = file,
                            rootPath      = directoryPath,
                            size          = streamReader.BaseStream.Length,
                            directDepends = new string[] { },
                            allDepends    = new string[] { }
                        };
                        infos.Add(info);
                    }
                }
            }

            return(infos);
        }
Example #4
0
 public static void AnalyzeObjectsCompleted(AssetBundleFileInfo info)
 {
     foreach (var kv in info.objDict)
     {
         AssetBundleFilesAnalyzeObject.ObjectAddToFileInfo(kv.Key, kv.Value, info);
         kv.Value.Dispose();
     }
     info.objDict.Clear();
 }
        public void AddBundleSceneInfo(AssetBundleFileInfo info, string[] scenePaths)
        {
#if UNITY_5_4_OR_NEWER
            foreach (var scenePath in scenePaths)
            {
                m_BundleSceneInfos.Enqueue(new BundleSceneInfo()
                {
                    fileInfo  = info,
                    sceneName = Path.GetFileNameWithoutExtension(scenePath),
                    scenePath = scenePath
                });
            }
#endif
        }
Example #6
0
        /// <summary>
        /// 分析Unity5方式的依赖构成
        /// </summary>
        /// <param name="directoryPath"></param>
        /// <returns></returns>
        private static List <AssetBundleFileInfo> AnalyzeManifestDepend(string directoryPath)
        {
            string manifestName = Path.GetFileName(directoryPath);
            string manifestPath = Path.Combine(directoryPath, manifestName);

            if (!File.Exists(manifestPath))
            {
                Debug.LogWarningFormat("{0} is not exists! Use AnalyzAllFiles ...", manifestPath);
                return(null);
            }
#if UNITY_5_3_OR_NEWER
            AssetBundle manifestAb = AssetBundle.LoadFromFile(manifestPath);
#else
            AssetBundle manifestAb = AssetBundle.CreateFromMemoryImmediate(File.ReadAllBytes(manifestPath));
#endif
            if (manifestAb == null)
            {
                Debug.LogErrorFormat("{0} ab load faild!", manifestPath);
                return(null);
            }

            List <AssetBundleFileInfo> assetBundleFileInfos = new List <AssetBundleFileInfo>();
#if UNITY_5 || UNITY_5_3_OR_NEWER
            AssetBundleManifest assetBundleManifest = manifestAb.LoadAsset <AssetBundleManifest>("assetbundlemanifest");
            var assetBundles = assetBundleManifest.GetAllAssetBundles();
            foreach (var assetBundle in assetBundles)
            {
                string path = Path.Combine(directoryPath, assetBundle);
                AssetBundleFileInfo assetBundleFileInfo = new AssetBundleFileInfo
                {
                    name          = assetBundle,
                    path          = path,
                    rootPath      = directoryPath,
                    size          = new FileInfo(path).Length,
                    directDepends = assetBundleManifest.GetDirectDependencies(assetBundle),
                    allDepends    = assetBundleManifest.GetAllDependencies(assetBundle)
                };
                assetBundleFileInfos.Add(assetBundleFileInfo);
            }
#endif
            manifestAb.Unload(true);
            return(assetBundleFileInfos);
        }
        private static void FillAssetByType(AssetBundleFileInfo info, string type, ExcelWorksheet ws, ref int startRow)
        {
            int count = info.GetAssetCount(type);

            if (count == 0)
            {
                return;
            }

            startRow++;
            ws.Cells[startRow, 1].Value = type + " (" + count + ")";
            SetRangeStyle(ws.Cells[startRow, 1, startRow, 4]);
            Color redColor = ColorTranslator.FromHtml("#FF0049");

            int startCol = 1;

            foreach (var fileInfo in info.assets)
            {
                if (fileInfo.type == type)
                {
                    if (startCol == 1)
                    {
                        startRow++;
                    }

                    ws.Cells[startRow, startCol].Value     = fileInfo.name;
                    ws.Cells[startRow, startCol].Hyperlink = fileInfo.detailHyperLink;

                    // 冗余则红色显示
                    if (fileInfo.includedBundles.Count > 1 && fileInfo.type != AssetFileInfoType.monoScript)
                    {
                        ws.Cells[startRow, startCol].Style.Font.Color.SetColor(redColor);
                    }

                    startCol++;
                    if (startCol > 4)
                    {
                        startCol = 1;
                    }
                }
            }
        }
Example #8
0
        /// <summary>
        /// 分析脚本的引用(这只在脚本在工程里时才有效)
        /// </summary>
        /// <param name="info"></param>
        /// <param name="o"></param>
        public static void AnalyzeObjectComponent(AssetBundleFileInfo info, Object o)
        {
            var go = o as GameObject;

            if (!go)
            {
                return;
            }

            var components = go.GetComponentsInChildren <Component>(true);

            foreach (var component in components)
            {
                if (!component)
                {
                    continue;
                }

                AnalyzeObjectReference(info, component);
            }
        }
        public static void Pack(string path, string outPath, AssetBundleUpdateInfo updateInfo)
        {
            int id             = 0;
            int totalSize      = 0;
            var allFileInfoDic = new Dictionary <int, AssetBundleFileInfo>();

            path = path.Replace("\\", "/");
            foreach (var assetBundle in updateInfo.PendingList.Values)
            {
                var fileInfo = new FileInfo(Path.Combine(path, assetBundle.AssetBundleName));
                if (!fileInfo.Exists)
                {
                    continue;
                }

                string filename = fileInfo.FullName.Replace("\\", "/");
                filename = filename.Replace(path + "/", "");
                int filesize = (int)fileInfo.Length;

                Debug.Log(id + " : " + filename + " 文件大小: " + filesize);

                var info = new AssetBundleFileInfo();
                info.Id         = id;
                info.Size       = filesize;
                info.Path       = filename;
                info.PathLength = new UTF8Encoding().GetBytes(filename).Length;
                info.Hash       = assetBundle.Hash;

                using (var fs = new FileStream(fileInfo.FullName, FileMode.Open))
                {
                    info.Data = new byte[fs.Length];
                    fs.Read(info.Data, 0, filesize);
                }

                allFileInfoDic.Add(id, info);
                id++;
                totalSize += filesize;
            }

            /**  遍历一个文件夹的所有文件 结束  **/

            Debug.Log("文件数量 : " + id);
            Debug.Log("文件总大小 : " + totalSize);

            /**  UPK中前面是写每个包的ID,StartPos,size,pathLength,path.
             * /**  更新文件在UPK中的起始点  **/
            int firstfilestartpos = 0 + 4;

            for (int index = 0; index < allFileInfoDic.Count; index++)
            {
                firstfilestartpos += 4 + 4 + 4 + 4 + allFileInfoDic[index].PathLength + 24;
            }

            for (int index = 0; index < allFileInfoDic.Count; index++)
            {
                int startpos;
                if (index == 0)
                {
                    startpos = firstfilestartpos;
                }
                else
                {
                    startpos = allFileInfoDic[index - 1].StartPos + allFileInfoDic[index - 1].Size; //上一个文件的开始+文件大小;
                }

                allFileInfoDic[index].StartPos = startpos;
            }

            if (File.Exists(outPath))
            {
                File.Delete(outPath);
            }

            using (var fileStream = new FileStream(outPath, FileMode.Create))
            {
                /**  文件总数量  **/
                var totaliddata = BitConverter.GetBytes(id);
                fileStream.Write(totaliddata, 0, totaliddata.Length);

                for (int index = 0; index < allFileInfoDic.Count; index++)
                {
                    /** 写入ID **/
                    var iddata = BitConverter.GetBytes(allFileInfoDic[index].Id);
                    fileStream.Write(iddata, 0, iddata.Length);

                    /**  写入StartPos  **/
                    var startposdata = BitConverter.GetBytes(allFileInfoDic[index].StartPos);
                    fileStream.Write(startposdata, 0, startposdata.Length);

                    /**  写入size  **/
                    var sizedata = BitConverter.GetBytes(allFileInfoDic[index].Size);
                    fileStream.Write(sizedata, 0, sizedata.Length);

                    /**  写入pathLength  **/
                    var pathLengthdata = BitConverter.GetBytes(allFileInfoDic[index].PathLength);
                    fileStream.Write(pathLengthdata, 0, pathLengthdata.Length);

                    /**  写入path  **/
                    var mypathdata = new UTF8Encoding().GetBytes(allFileInfoDic[index].Path);
                    fileStream.Write(mypathdata, 0, mypathdata.Length);

                    /**  写入md5  **/
                    var md5Data = new UTF8Encoding().GetBytes(allFileInfoDic[index].Hash);
                    fileStream.Write(md5Data, 0, md5Data.Length);

                    Debug.Log(allFileInfoDic[index].ToString());

                    var abi = updateInfo.GetAssetBundleInfoHash(allFileInfoDic[index].Hash);
                    if (abi != null)
                    {
                        abi.StartOffset = allFileInfoDic[index].StartPos;
                    }
                }

                /**  写入文件数据  **/
                foreach (var infopair in allFileInfoDic)
                {
                    var info        = infopair.Value;
                    int size        = info.Size;
                    int processSize = 0;
                    while (processSize < size)
                    {
                        var tmpdata = size - processSize < 1024 ? new byte[size - processSize] : new byte[1024];
                        fileStream.Write(info.Data, processSize, tmpdata.Length);

                        processSize += tmpdata.Length;
                    }
                }
            }
            Debug.Log("打包结束");
        }
        public static void ObjectAddToFileInfo(Object obj, SerializedObject serializedObject, AssetBundleFileInfo info)
        {
            if (obj == null)
            {
                return;
            }

            string name2 = obj.name;
            string type  = obj.GetType().ToString();

            if (type.StartsWith("UnityEngine.", System.StringComparison.Ordinal))
            {
                type = type.Substring(12);

                // 如果是内置的组件,就不当作是资源
                if (obj as Component)
                {
                    return;
                }
            }
            else if (string.Equals(type, "UnityEditor.Animations.AnimatorController", System.StringComparison.Ordinal))
            {
                type = "AnimatorController";
            }
            else if (string.Equals(type, "UnityEditorInternal.AnimatorController", System.StringComparison.Ordinal))
            {
                type = "AnimatorController";
            }
            else if (string.Equals(type == "UnityEditor.MonoScript", System.StringComparison.Ordinal))
            {
                MonoScript ms    = obj as MonoScript;
                string     type2 = ms.GetClass().ToString();
                if (type2.StartsWith("UnityEngine.", System.StringComparison.Ordinal))
                {
                    // 内置的脚本对象也不显示出来
                    return;
                }

                // 外部的组件脚本,保留下来
                type = "MonoScript";
            }
            else
            {
                // 外部的组件脚本,走上面的MonoScript
                if (obj as Component)
                {
                    return;
                }
                // 外部的序列化对象,已经被脚本给分析完毕了,不需要再添加进来
                if (obj as ScriptableObject)
                {
                    return;
                }

                Debug.LogError("What's this? " + type);
                return;
            }

            // 内建的资源排除掉
            string assetPath = AssetDatabase.GetAssetPath(obj);

            if (!string.IsNullOrEmpty(assetPath))
            {
                return;
            }

            long guid;

            if (info.isScene)
            {
                // 场景的话,没法根据PathID来确定唯一性,那么就认为每个场景用到的资源都不一样
                guid = (info.name + name2 + type).GetHashCode();
            }
            else
            {
                SerializedProperty pathIdProp = serializedObject.FindProperty("m_LocalIdentfierInFile");
#if UNITY_5 || UNITY_5_3_OR_NEWER
                guid = pathIdProp.longValue;
#else
                guid = pathIdProp.intValue;
#endif
            }

            if (info.IsAssetContain(guid))
            {
                return;
            }

            AssetFileInfo info2 = AssetBundleFilesAnalyze.GetAssetFileInfo(guid);
            info2.name = name2;
            info2.type = type;
            info2.includedBundles.Add(info);
            if (info2.detailHyperLink == null)
            {
                // 初次创建对象时链接为空
                info2.detailHyperLink = new OfficeOpenXml.ExcelHyperLink(System.String.Empty, info2.name);
                info2.propertys       = AnalyzeObject(obj, serializedObject, info.rootPath, info.name);
            }

            info.assets.Add(info2);
        }
        private static void FillAssetDepends(AssetBundleFileInfo info, ExcelWorksheet ws, ref int startRow)
        {
            if (info.allDepends == null && info.beDepends == null)
            {
                return;
            }
            if (info.allDepends != null && info.beDepends != null &&
                info.allDepends.Length == 0 && info.beDepends.Length == 0)
            {
                return;
            }

            int rowAdd   = 0;
            int titleRow = ++startRow;

            if (info.allDepends != null && info.allDepends.Length != 0)
            {
                ws.Cells[titleRow, 3].Value = "它依赖哪些AssetBundle文件? (" + info.allDepends.Length + ")";
                SetRangeStyle(ws.Cells[titleRow, 3, titleRow, 4]);

                int dependRow = titleRow;
                foreach (var depend in info.allDepends)
                {
                    if (string.IsNullOrEmpty(depend))
                    {
                        continue;
                    }
                    dependRow++;
                    var dependInfo = AssetBundleFilesAnalyze.GetAssetBundleFileInfo(depend);
                    ws.Cells[dependRow, 3].Value               = dependInfo.name;
                    ws.Cells[dependRow, 3].Hyperlink           = dependInfo.detailHyperLink;
                    ws.Cells[dependRow, 3, dependRow, 4].Merge = true;
                }

                rowAdd = dependRow - titleRow;
            }

            if (info.beDepends != null && info.beDepends.Length != 0)
            {
                ws.Cells[titleRow, 1].Value = "哪些AssetBundle文件依赖它? (" + info.beDepends.Length + ")";
                SetRangeStyle(ws.Cells[titleRow, 1, titleRow, 2]);

                int dependRow = titleRow;
                foreach (var depend in info.beDepends)
                {
                    dependRow++;
                    var dependInfo = AssetBundleFilesAnalyze.GetAssetBundleFileInfo(depend);
                    ws.Cells[dependRow, 1].Value               = dependInfo.name;
                    ws.Cells[dependRow, 1].Hyperlink           = dependInfo.detailHyperLink;
                    ws.Cells[dependRow, 1, dependRow, 2].Merge = true;
                }

                int rowAdd2 = dependRow - titleRow;
                if (rowAdd2 > rowAdd)
                {
                    rowAdd = rowAdd2;
                }
            }

            startRow += rowAdd;
        }