From efd06648ade2f455b3f7eecfd6388901bcb84404 Mon Sep 17 00:00:00 2001 From: VaDiM Date: Tue, 21 Nov 2023 01:35:25 +0300 Subject: [PATCH] Add support for separate PreloadData https://github.com/Perfare/AssetStudio/issues/690 https://docs.unity.cn/550/Documentation/Manual/AssetBundleInternalStructure.html --- AssetStudio/AssetsManager.cs | 3 +++ AssetStudio/Classes/AssetBundle.cs | 34 ++++++++++++++++++++++++----- AssetStudio/Classes/PreloadData.cs | 35 ++++++++++++++++++++++++++++++ AssetStudioCLI/Studio.cs | 24 ++++++++++++++------ AssetStudioGUI/Studio.cs | 23 ++++++++++++++------ 5 files changed, 99 insertions(+), 20 deletions(-) create mode 100644 AssetStudio/Classes/PreloadData.cs diff --git a/AssetStudio/AssetsManager.cs b/AssetStudio/AssetsManager.cs index b00ef27..fc9283b 100644 --- a/AssetStudio/AssetsManager.cs +++ b/AssetStudio/AssetsManager.cs @@ -532,6 +532,9 @@ namespace AssetStudio case ClassIDType.PlayerSettings: obj = new PlayerSettings(objectReader); break; + case ClassIDType.PreloadData: + obj = new PreloadData(objectReader); + break; case ClassIDType.RectTransform: obj = new RectTransform(objectReader); break; diff --git a/AssetStudio/Classes/AssetBundle.cs b/AssetStudio/Classes/AssetBundle.cs index 3883fce..0a6fd1c 100644 --- a/AssetStudio/Classes/AssetBundle.cs +++ b/AssetStudio/Classes/AssetBundle.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Collections.Generic; namespace AssetStudio { @@ -23,22 +20,47 @@ namespace AssetStudio { public PPtr[] m_PreloadTable; public KeyValuePair[] m_Container; + public string m_AssetBundleName; + public string[] m_Dependencies; + public bool m_IsStreamedSceneAssetBundle; public AssetBundle(ObjectReader reader) : base(reader) { var m_PreloadTableSize = reader.ReadInt32(); m_PreloadTable = new PPtr[m_PreloadTableSize]; - for (int i = 0; i < m_PreloadTableSize; i++) + for (var i = 0; i < m_PreloadTableSize; i++) { m_PreloadTable[i] = new PPtr(reader); } var m_ContainerSize = reader.ReadInt32(); m_Container = new KeyValuePair[m_ContainerSize]; - for (int i = 0; i < m_ContainerSize; i++) + for (var i = 0; i < m_ContainerSize; i++) { m_Container[i] = new KeyValuePair(reader.ReadAlignedString(), new AssetInfo(reader)); } + + var m_MainAsset = new AssetInfo(reader); + + if (version[0] > 4 || (version[0] == 4 && version[1] >= 2)) //4.2 and up + { + var m_RuntimeCompatibility = reader.ReadUInt32(); + } + + if (version[0] >= 5) //5.0 and up + { + m_AssetBundleName = reader.ReadAlignedString(); + + var m_DependenciesSize = reader.ReadInt32(); + m_Dependencies = new string[m_DependenciesSize]; + + for (var i = 0; i < m_DependenciesSize; i++) + { + m_Dependencies[i] = reader.ReadAlignedString(); + } + + m_IsStreamedSceneAssetBundle = reader.ReadBoolean(); + } } } } diff --git a/AssetStudio/Classes/PreloadData.cs b/AssetStudio/Classes/PreloadData.cs new file mode 100644 index 0000000..a1f2224 --- /dev/null +++ b/AssetStudio/Classes/PreloadData.cs @@ -0,0 +1,35 @@ +namespace AssetStudio +{ + public sealed class PreloadData : NamedObject + { + public PPtr[] m_Assets; + + public PreloadData(ObjectReader reader) : base(reader) + { + var m_PreloadTableSize = reader.ReadInt32(); + m_Assets = new PPtr[m_PreloadTableSize]; + for (var i = 0; i < m_PreloadTableSize; i++) + { + m_Assets[i] = new PPtr(reader); + } + + /* + if (version[0] >= 5) //5.0 and up + { + var m_DependenciesSize = reader.ReadInt32(); + var m_Dependencies = new string[m_DependenciesSize]; + + for (var i = 0; i < m_DependenciesSize; i++) + { + m_Dependencies[i] = reader.ReadAlignedString(); + } + } + + if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 2)) //2018.2 and up + { + var m_ExplicitDataLayout = reader.ReadBoolean(); + } + */ + } + } +} diff --git a/AssetStudioCLI/Studio.cs b/AssetStudioCLI/Studio.cs index d715566..f210f0c 100644 --- a/AssetStudioCLI/Studio.cs +++ b/AssetStudioCLI/Studio.cs @@ -62,6 +62,7 @@ namespace AssetStudioCLI var i = 0; foreach (var assetsFile in assetsManager.assetsFileList) { + var preloadTable = Array.Empty>(); foreach (var asset in assetsFile.Objects) { var assetItem = new AssetItem(asset); @@ -70,22 +71,31 @@ namespace AssetStudioCLI var isExportable = false; switch (asset) { + case PreloadData m_PreloadData: + preloadTable = m_PreloadData.m_Assets; + break; case AssetBundle m_AssetBundle: + var isStreamedSceneAssetBundle = m_AssetBundle.m_IsStreamedSceneAssetBundle; + if (!isStreamedSceneAssetBundle) + { + preloadTable = m_AssetBundle.m_PreloadTable; + } + assetItem.Text = string.IsNullOrEmpty(m_AssetBundle.m_AssetBundleName) ? m_AssetBundle.m_Name : m_AssetBundle.m_AssetBundleName; + foreach (var m_Container in m_AssetBundle.m_Container) { var preloadIndex = m_Container.Value.preloadIndex; - var preloadSize = m_Container.Value.preloadSize; + var preloadSize = isStreamedSceneAssetBundle ? preloadTable.Length : m_Container.Value.preloadSize; var preloadEnd = preloadIndex + preloadSize; - for (int k = preloadIndex; k < preloadEnd; k++) + for (var k = preloadIndex; k < preloadEnd; k++) { - var pptr = m_AssetBundle.m_PreloadTable[k]; + var pptr = preloadTable[k]; if (pptr.TryGet(out var obj)) { containers[obj] = m_Container.Key; } } } - assetItem.Text = m_AssetBundle.m_Name; break; case ResourceManager m_ResourceManager: foreach (var m_Container in m_ResourceManager.m_Container) @@ -110,7 +120,7 @@ namespace AssetStudioCLI if (!string.IsNullOrEmpty(m_VideoClip.m_OriginalPath)) assetItem.FullSize = asset.byteSize + m_VideoClip.m_ExternalResources.m_Size; assetItem.Text = m_VideoClip.m_Name; - break; + break; case Shader m_Shader: assetItem.Text = m_Shader.m_ParsedForm?.m_Name ?? m_Shader.m_Name; break; @@ -152,9 +162,9 @@ namespace AssetStudioCLI } foreach (var asset in fileAssetsList) { - if (containers.ContainsKey(asset.Asset)) + if (containers.TryGetValue(asset.Asset, out var container)) { - asset.Container = containers[asset.Asset]; + asset.Container = container; } } parsedAssetsList.AddRange(fileAssetsList); diff --git a/AssetStudioGUI/Studio.cs b/AssetStudioGUI/Studio.cs index 94ab0c2..02e6ee0 100644 --- a/AssetStudioGUI/Studio.cs +++ b/AssetStudioGUI/Studio.cs @@ -162,6 +162,8 @@ namespace AssetStudioGUI Progress.Reset(); foreach (var assetsFile in assetsManager.assetsFileList) { + var preloadTable = Array.Empty>(); + foreach (var asset in assetsFile.Objects) { var assetItem = new AssetItem(asset); @@ -170,6 +172,9 @@ namespace AssetStudioGUI var exportable = false; switch (asset) { + case PreloadData m_PreloadData: + preloadTable = m_PreloadData.m_Assets; + break; case GameObject m_GameObject: assetItem.Text = m_GameObject.m_Name; break; @@ -187,7 +192,7 @@ namespace AssetStudioGUI break; case VideoClip m_VideoClip: if (!string.IsNullOrEmpty(m_VideoClip.m_OriginalPath)) - assetItem.FullSize = asset.byteSize + (long)m_VideoClip.m_ExternalResources.m_Size; + assetItem.FullSize = asset.byteSize + m_VideoClip.m_ExternalResources.m_Size; assetItem.Text = m_VideoClip.m_Name; exportable = true; break; @@ -226,17 +231,23 @@ namespace AssetStudioGUI productName = m_PlayerSettings.productName; break; case AssetBundle m_AssetBundle: + var isStreamedSceneAssetBundle = m_AssetBundle.m_IsStreamedSceneAssetBundle; + if (!isStreamedSceneAssetBundle) + { + preloadTable = m_AssetBundle.m_PreloadTable; + } + assetItem.Text = string.IsNullOrEmpty(m_AssetBundle.m_AssetBundleName) ? m_AssetBundle.m_Name : m_AssetBundle.m_AssetBundleName; + foreach (var m_Container in m_AssetBundle.m_Container) { var preloadIndex = m_Container.Value.preloadIndex; - var preloadSize = m_Container.Value.preloadSize; + var preloadSize = isStreamedSceneAssetBundle ? preloadTable.Length : m_Container.Value.preloadSize; var preloadEnd = preloadIndex + preloadSize; - for (int k = preloadIndex; k < preloadEnd; k++) + for (var k = preloadIndex; k < preloadEnd; k++) { - containers.Add((m_AssetBundle.m_PreloadTable[k], m_Container.Key)); + containers.Add((preloadTable[k], m_Container.Key)); } } - assetItem.Text = m_AssetBundle.m_Name; break; case ResourceManager m_ResourceManager: foreach (var m_Container in m_ResourceManager.m_Container) @@ -349,7 +360,6 @@ namespace AssetStudioGUI Progress.Report(++j, assetsFileCount); } treeNodeDictionary.Clear(); - objectAssetItemDic.Clear(); return (productName, treeNodeCollection); @@ -387,7 +397,6 @@ namespace AssetStudioGUI typeMap.Add(assetsFile.unityVersion, items); } } - return typeMap; }