using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor.AddressableAssets.Settings;
using UnityEditor.Build.Content;
using UnityEngine;
using UnityEngine.AddressableAssets.ResourceLocators;
using UnityEngine.ResourceManagement.ResourceProviders;
namespace UnityEditor.AddressableAssets.Build.Layout
{
///
/// A storage class used to gather data about an Addressable build.
///
[Serializable]
public class BuildLayout
{
///
/// Helper class to wrap header values for BuildLayout
///
public class LayoutHeader
{
///
/// Build layout for this header
///
internal BuildLayout m_BuildLayout;
///
/// Build Platform Addressables build is targeting
///
public BuildTarget BuildTarget
{
get
{
if (m_BuildLayout == null)
return BuildTarget.NoTarget;
return m_BuildLayout.BuildTarget;
}
}
///
/// Hash of the build results
///
public string BuildResultHash
{
get
{
if (m_BuildLayout == null)
return null;
return m_BuildLayout.BuildResultHash;
}
}
///
/// If the build was a new build or an update for a previous build
///
public BuildType BuildType
{
get
{
if (m_BuildLayout == null)
return BuildType.NewBuild;
return m_BuildLayout.BuildType;
}
}
///
/// DateTime at the start of building Addressables
///
public DateTime BuildStart
{
get
{
if (m_BuildLayout == null)
return DateTime.MinValue;
return m_BuildLayout.BuildStart;
}
}
///
/// Time in seconds taken to build Addressables Content
///
public double Duration
{
get
{
if (m_BuildLayout == null)
return 0;
return m_BuildLayout.Duration;
}
}
///
/// Null or Empty if the build completed successfully, else contains error causing the failure
///
public string BuildError
{
get
{
if (m_BuildLayout == null)
return "";
return m_BuildLayout.BuildError;
}
}
}
///
/// Helper object to get header values for this build layout
///
public LayoutHeader Header
{
get
{
if (m_Header == null)
m_Header = new LayoutHeader() {m_BuildLayout = this};
return m_Header;
}
}
private LayoutHeader m_Header;
#region HeaderValues // Any values in here should also be in BuildLayoutHeader class
///
/// Build Platform Addressables build is targeting
///
public BuildTarget BuildTarget;
///
/// Hash of the build results
///
public string BuildResultHash;
///
/// If the build was a new build or an update for a previous build
///
public BuildType BuildType;
///
/// DateTime at the start of building Addressables
///
public DateTime BuildStart
{
get
{
if (m_BuildStartDateTime.Year > 2000)
return m_BuildStartDateTime;
if (DateTime.TryParse(BuildStartTime, out DateTime result))
{
m_BuildStartDateTime = result;
return m_BuildStartDateTime;
}
return DateTime.MinValue;
}
set
{
BuildStartTime = value.ToString();
}
}
private DateTime m_BuildStartDateTime;
[SerializeField]
internal string BuildStartTime;
///
/// Time in seconds taken to build Addressables Content
///
public double Duration;
///
/// Null or Empty if the build completed successfully, else contains error causing the failure
///
public string BuildError;
#endregion // End of header values
///
/// Version of the Unity edtior used to perform the build.
///
public string UnityVersion;
///
/// Version of the Addressables package used to perform the build.
///
public string PackageVersion;
///
/// Player build version for the build, this is a timestamp if PlayerVersionOverride is not set in the settings
///
public string PlayerBuildVersion;
///
/// Settings used by the Addressables settings at the time of building
///
public AddressablesEditorData AddressablesEditorSettings;
///
/// Values used by the Addressables runtime
///
public AddressablesRuntimeData AddressablesRuntimeSettings;
///
/// Name of the build script to build
///
public string BuildScript;
///
/// Default group at the time of building
///
[SerializeReference]
public Group DefaultGroup;
///
/// The Addressable Groups that reference this data
///
[SerializeReference]
public List Groups = new List();
///
/// The List of AssetBundles that were built without a group associated to them, such as the BuiltIn Shaders Bundle and the MonoScript Bundle
///
[SerializeReference]
public List BuiltInBundles = new List();
///
/// List of assets with implicitly included Objects
///
public List DuplicatedAssets = new List();
///
/// The build path on disk of the default local content catalog
///
[SerializeField]
internal string LocalCatalogBuildPath;
///
/// The build path of the remote content catalog, if one was built
///
[SerializeField]
internal string RemoteCatalogBuildPath;
internal string m_FilePath;
private bool m_HeaderRead = false;
private bool m_BodyRead = false;
private FileStream m_FileStream = null;
private StreamReader m_StreamReader = null;
///
/// Used for serialising the header info for the BuildLayout.
/// Names must match values in BuildLayout class
///
[Serializable]
private class BuildLayoutHeader
{
public BuildTarget BuildTarget;
public string BuildResultHash;
public BuildType BuildType;
public string BuildStartTime;
public double Duration;
public string BuildError;
}
///
///
///
/// Path to the BuildLayout json file on disk
/// If the basic header information should be read
/// If the full build layout should be read
///
public static BuildLayout Open(string path, bool readHeader = true, bool readFullFile = false)
{
if (string.IsNullOrEmpty(path) || !System.IO.File.Exists(path))
{
Debug.LogError($"Invalid path provided : {path}");
return null;
}
BuildLayout readLayout = new BuildLayout
{
m_FilePath = path
};
if (readFullFile)
readLayout.ReadFull();
else if (readHeader)
readLayout.ReadHeader();
return readLayout;
}
///
/// Writes json file for the build layout to the destination path
///
/// File path to write build layout
/// If json should be written using pretty print
public void WriteToFile(string destinationPath, bool prettyPrint)
{
Directory.CreateDirectory(Path.GetDirectoryName(destinationPath));
string versionElementString = "\"UnityVersion\":";
string headerJson = null;
string bodyJson = JsonUtility.ToJson(this, prettyPrint);
if (prettyPrint)
{
BuildLayoutHeader header = new BuildLayoutHeader()
{
BuildTarget = this.BuildTarget,
BuildResultHash = this.BuildResultHash,
BuildType = this.BuildType,
BuildStartTime = this.BuildStartTime,
Duration = this.Duration,
BuildError = this.BuildError
};
headerJson = JsonUtility.ToJson(header, false);
headerJson = headerJson.Remove(headerJson.Length - 1, 1) + ',';
}
int index = bodyJson.IndexOf(versionElementString);
if (prettyPrint)
bodyJson = bodyJson.Remove(0, index);
else
bodyJson = bodyJson.Insert(index, "\n");
using (FileStream s = System.IO.File.Open(destinationPath, FileMode.Create))
{
using (StreamWriter sw = new StreamWriter(s))
{
if (prettyPrint)
sw.WriteLine(headerJson);
sw.Write(bodyJson);
}
}
}
///
/// Closes streams for loading the build layout
///
public void Close()
{
if (m_StreamReader != null)
{
m_StreamReader.Close();
m_StreamReader = null;
}
if (m_FileStream != null)
{
m_FileStream.Close();
m_FileStream = null;
}
}
///
/// Reads basic information about the build layout
///
/// If false, the file will be closed after reading the header line.
/// true is successful, else false
public bool ReadHeader(bool keepFileStreamsActive = false)
{
if (m_HeaderRead)
return true;
if (string.IsNullOrEmpty(m_FilePath))
{
Debug.LogError("Cannot read BuildLayout header, A file has not been selected to open. Open must be called before reading any data");
return false;
}
try
{
if (m_FileStream == null)
{
m_FileStream = System.IO.File.Open(m_FilePath, FileMode.Open);
m_StreamReader = new StreamReader(m_FileStream);
}
string fileJsonText = m_StreamReader.ReadLine();
int lastComma = fileJsonText.LastIndexOf(',');
if (lastComma > 0)
{
fileJsonText = fileJsonText.Remove(lastComma) + '}';
try
{
EditorJsonUtility.FromJsonOverwrite(fileJsonText, this);
}
catch (Exception e)
{
Debug.LogError($"Failed to read header for BuildLayout at {m_FilePath}, with exception: {e.Message}");
return false;
}
}
else
{
Debug.LogError($"Failed to read header for BuildLayout at {m_FilePath}, invalid json format");
return false;
}
m_HeaderRead = true;
}
catch (Exception e)
{
Debug.LogException(e);
return false;
}
finally
{
if (!keepFileStreamsActive)
Close();
}
return true;
}
///
/// Reads the full build layout data from file
///
/// true is successful, else false
public bool ReadFull()
{
if (m_BodyRead)
return true;
if (string.IsNullOrEmpty(m_FilePath))
{
Debug.LogError("Cannot read BuildLayout header, BuildLayout has not open for a file");
return false;
}
try
{
if (m_FileStream == null)
{
m_FileStream = System.IO.File.Open(m_FilePath, FileMode.Open);
m_StreamReader = new StreamReader(m_FileStream);
}
else if (m_HeaderRead)
{
// reset to read the whole file
m_FileStream.Position = 0;
m_StreamReader.DiscardBufferedData();
}
string fileJsonText = m_StreamReader.ReadToEnd();
EditorJsonUtility.FromJsonOverwrite(fileJsonText, this);
m_HeaderRead = true;
m_BodyRead = true;
}
catch (Exception e)
{
Debug.LogError($"Failed to read header for BuildLayout at {m_FilePath}, with exception: {e.Message}");
return false;
}
finally
{
Close();
}
return true;
}
///
/// Values set for the AddressablesAssetSettings at the time of building
///
[Serializable]
public class AddressablesEditorData
{
///
/// Hash value of the settings at the time of building
///
public string SettingsHash;
///
/// Active Addressables profile set at time of Building
///
public Profile ActiveProfile;
///
/// Addressables setting value set for building the remote catalog
///
public bool BuildRemoteCatalog;
///
/// Load path for the remote catalog if enabled
///
public string RemoteCatalogLoadPath;
///
/// Addressables setting value set for bundling the local catalog
///
public bool BundleLocalCatalog;
///
/// Addressables setting value set for optimising the catalog size
///
public bool OptimizeCatalogSize;
///
/// Addressables setting value set for time out when downloading catalogs
///
public int CatalogRequestsTimeout;
///
/// Runtime setting value set for the maximum number of concurrent web requests
///
public int MaxConcurrentWebRequests;
///
/// Addressables setting value set for is to update the remote catalog on startup
///
public bool DisableCatalogUpdateOnStartup;
///
/// Addressables setting value set for if the build created unique bundle ids
///
public bool UniqueBundleIds;
///
/// Addressables setting value set for if the build used non recursive dependency calculation
///
public bool NonRecursiveBuilding;
///
/// Addressables setting value set for if the build used contiguous bundle objects
///
public bool ContiguousBundles;
///
/// Addressables setting value set for disabling sub asset representation in the Bundle
///
public bool DisableSubAssetRepresentations;
///
/// Internal naming prefix of the built in shaders bundle
///
public string ShaderBundleNaming;
///
/// Internal naming prefix of the monoScript bundle,
/// No MonoScript bundle is built if set to disabled
///
public string MonoScriptBundleNaming;
///
/// Addressables setting value set for is the unity version was stripped from the built bundles
///
public bool StripUnityVersionFromBundleBuild;
}
///
/// Values set for runtime initialisation of Addressables
///
[Serializable]
public class AddressablesRuntimeData
{
///
/// Runtime setting value set for if the runtime will submit profiler events
///
public bool ProfilerEvents;
///
/// Runtime setting value set for if resource manager exceptions are logged or not
///
public bool LogResourceManagerExceptions;
///
/// Runtime setting value set for catalogs to load (First catalog found in the list is used)
///
public List CatalogLoadPaths = new List();
///
/// Hash of the build catalog
///
public string CatalogHash;
}
///
/// Information about the AssetBundleObject
///
[Serializable]
public class AssetBundleObjectInfo
{
///
/// The size, in bytes, of the AssetBundleObject
///
public ulong Size;
}
///
/// Key value pair of string type
///
[Serializable]
public struct StringPair
{
///
/// String key
///
public string Key;
///
/// String value
///
public string Value;
}
///
/// Addressables Profile data
///
[Serializable]
public class Profile
{
///
/// Name of the profile
///
public string Name;
///
/// ID assigned within the ProfileSettings of the profile
///
public string Id;
///
/// Profile variables assigned to the profile
///
public StringPair[] Values;
}
///
/// Data about the AddressableAssetGroup that gets processed during a build.
///
[Serializable]
public class Group
{
///
/// The Name of the AdressableAssetGroup
///
public string Name;
///
/// The Guid of the AddressableAssetGroup
///
public string Guid;
///
/// The packing mode as defined by the BundledAssetGroupSchema on the AddressableAssetGroup
///
public string PackingMode;
///
/// A list of the AssetBundles associated with the Group
///
[SerializeReference]
public List Bundles = new List();
///
/// Data about the AddressableAssetGroupSchemas associated with the Group
///
[SerializeReference]
public List Schemas = new List();
}
///
/// Data container for AddressableAssetGroupSchemas
///
[Serializable]
public class SchemaData : ISerializationCallbackReceiver
{
///
/// The Guid of the AddressableAssetGroupSchema
///
public string Guid;
///
/// The class type of the AddressableAssetGroupSchema
///
public string Type;
///
/// These key-value-pairs include data about the AddressableAssetGroupSchema, such as PackingMode and Compression.
///
public List> KvpDetails = new List>();
[SerializeField]
private StringPair[] SchemaDataPairs;
///
/// Converts the unserializable KvpDetails to a serializable type for writing
///
public void OnBeforeSerialize()
{
SchemaDataPairs = new StringPair[KvpDetails.Count];
for (int i = 0; i < SchemaDataPairs.Length; ++i)
SchemaDataPairs[i] = new StringPair() {Key = KvpDetails[i].Item1, Value = KvpDetails[i].Item2};
}
///
/// Writes data to KvpDetails after Deserializing to temporary data fields
///
public void OnAfterDeserialize()
{
for (int i = 0; i < SchemaDataPairs.Length; ++i)
KvpDetails.Add(new Tuple(SchemaDataPairs[i].Key, SchemaDataPairs[i].Value));
SchemaDataPairs = null;
}
}
///
/// Data store for AssetBundle information.
///
[Serializable]
public class Bundle
{
///
/// The name of the AssetBundle
///
public string Name;
///
/// Name used to identify the asset bundle
///
public string InternalName;
///
/// The file size of the AssetBundle on disk, in bytes
///
public ulong FileSize;
///
/// Status of the bundle after an update build
///
public BundleBuildStatus BuildStatus;
///
/// The file size of all of the Expanded Dependencies of this AssetBundle, in bytes
/// Expanded dependencies are the dependencies of this AssetBundle's dependencies
///
public ulong ExpandedDependencyFileSize;
///
/// The file size
///
public ulong DependencyFileSize;
///
/// The file size of the AssetBundle on disk when uncompressed, in bytes
///
public ulong UncompressedFileSize
{
get
{
ulong total = 0;
foreach (File file in Files)
total += file.UncompressedSize;
return total;
}
}
///
/// The number of Assets contained within the bundle
///
public int AssetCount = 0;
///
/// Represents a dependency from the containing Bundle to dependentBundle, with AssetDependencies representing each of the assets in parentBundle that create the link to dependentBundle
///
[Serializable]
public class BundleDependency
{
///
/// The bundle that the parent bundle depends on
///
[SerializeReference]
public Bundle DependencyBundle;
///
/// The list of assets that link the parent bundle to the DependencyBundle
///
public List AssetDependencies;
///
/// Percentage of Efficiency asset usage that uses the entire dependency tree of this bundle dependency.
/// This includes DependencyBundle and all bundles beneath it.
/// Value is equal to [Total Filesize of Dependency Assets] / [Total size of all dependency bundles on disk]
/// Example: There are 3 bundles A, B, and C, that are each 10 MB on disk. A depends on 2 MB worth of assets in B, and B depends on 4 MB worth of assets in C.
/// The Efficiency of the dependencyLink from A->B would be 2/10 -> 20% and the ExpandedEfficiency of A->B would be (2 + 4)/(10 + 10) -> 6/20 -> 30%
///
public float ExpandedEfficiency;
///
/// The Efficiency of the connection between the parent bundle and DependencyBundle irrespective of the full dependency tree below DependencyBundle.
/// Value is equal to [Serialized Filesize of assets In Dependency Bundle Referenced By Parent]/[Total size of Dependency Bundle on disk]
/// Example: Given two Bundles A and B that are each 10 MB on disk, and A depends on 5 MB worth of assets in B, then the Efficiency of DependencyLink A->B is 5/10 = .5
///
public float Efficiency;
private HashSet referencedAssets = new HashSet();
///
/// The number of uniquely assets that the parent bundle uniquely references in dependency bundle. This is used to calculate Efficiency without double counting.
///
internal ulong referencedAssetsFileSize = 0;
internal BundleDependency(Bundle b)
{
DependencyBundle = b;
AssetDependencies = new List();
}
internal void CreateAssetDependency(ExplicitAsset root, ExplicitAsset dependencyAsset)
{
if (referencedAssets.Contains(dependencyAsset))
return;
referencedAssets.Add(dependencyAsset);
AssetDependencies.Add(new AssetDependency(root, dependencyAsset));
referencedAssetsFileSize += dependencyAsset.SerializedSize;
}
///
/// Represents a dependency from a root Asset to a dependent Asset.
///
[Serializable]
public struct AssetDependency
{
[SerializeReference]
internal ExplicitAsset rootAsset;
[SerializeReference]
internal ExplicitAsset dependencyAsset;
internal AssetDependency(ExplicitAsset root, ExplicitAsset depAsset)
{
rootAsset = root;
dependencyAsset = depAsset;
}
}
}
internal Dictionary BundleDependencyMap = new Dictionary();
///
/// A list of bundles that this bundle depends upon.
///
[SerializeField]
public BundleDependency[] BundleDependencies = Array.Empty();
///
/// Convert BundleDependencyMap to a format that is able to be serialized and plays nicer with
/// CalculateEfficiency - this must be called on a bundle before CalculateEfficiency can be called.
///
internal void SerializeBundleToBundleDependency()
{
BundleDependencies = new BundleDependency[BundleDependencyMap.Values.Count];
BundleDependencyMap.Values.CopyTo(BundleDependencies, 0);
}
///
/// Updates the BundleDependency from the current bundle to the bundle that contains referencedAsset. If no such BundleDependency exists,
/// one is created. Does nothing if rootAsset's bundle is not the current bundle or
/// if the two assets are in the same bundle.
///
///
///
internal void UpdateBundleDependency(ExplicitAsset rootAsset, ExplicitAsset referencedAsset)
{
if (rootAsset.Bundle != this || referencedAsset.Bundle == rootAsset.Bundle)
return;
if (!BundleDependencyMap.ContainsKey(referencedAsset.Bundle))
BundleDependencyMap.Add(referencedAsset.Bundle, new BundleDependency(referencedAsset.Bundle));
BundleDependencyMap[referencedAsset.Bundle].CreateAssetDependency(rootAsset, referencedAsset);
}
// Helper struct for calculating Efficiency
internal struct EfficiencyInfo
{
internal ulong totalAssetFileSize;
internal ulong referencedAssetFileSize;
}
///
/// The Compression method used for the AssetBundle.
///
public string Compression;
///
/// Cyclic redundancy check of the content contained inside of the asset bundle.
/// This value will not change between identical asset bundles with different compression options.
///
public uint CRC;
///
/// The hash version of the contents contained inside of the asset bundle.
/// This value will not change between identical asset bundles with different compression options.
///
public Hash128 Hash;
///
/// A reference to the Group data that this AssetBundle was generated from
///
[SerializeReference]
public Group Group;
///
/// Path Provider uses to load the Asset Bundle
///
public string LoadPath;
///
/// Provider used to load the Asset Bundle
///
public string Provider;
///
/// Result provided by the Provider loading the Asset Bundle
///
public string ResultType;
///
/// List of the Files referenced by the AssetBundle
///
[SerializeReference]
public List Files = new List();
///
/// A list of the bundles that directly depend on this AssetBundle
///
[SerializeReference]
public List DependentBundles = new List();
///
/// A list of the direct dependencies of the AssetBundle
///
[SerializeReference]
public List Dependencies;
///
/// The second order dependencies and greater of a bundle
///
[SerializeReference]
public List ExpandedDependencies;
}
///
/// Data store for resource files generated by the build pipeline and referenced by a main File
///
[Serializable]
public class SubFile
{
///
/// The name of the sub-file
///
public string Name;
///
/// If the main File is a serialized file, this will be true.
///
public bool IsSerializedFile;
///
/// The size of the sub-file, in bytes
///
public ulong Size;
}
///
/// Data store for the main File created for the AssetBundle
///
[Serializable]
public class File
{
///
/// The name of the File.
///
public string Name;
///
/// The AssetBundle data that relates to a built file.
///
[SerializeReference]
public Bundle Bundle;
///
/// The file size of the AssetBundle on disk when uncompressed, in bytes
///
public ulong UncompressedSize
{
get
{
ulong total = 0;
foreach (SubFile subFile in SubFiles)
total += subFile.Size;
return total;
}
}
///
/// List of the resource files created by the build pipeline that a File references
///
[SerializeReference]
public List SubFiles = new List();
///
/// A list of the explicit asset defined in the AssetBundle
///
[SerializeReference]
public List Assets = new List();
///
/// A list of implicit assets built into the AssetBundle, typically through references by Assets that are explicitly defined.
///
[SerializeReference]
public List OtherAssets = new List();
[SerializeReference]
internal List ExternalReferences = new List();
///
/// The final filename of the AssetBundle file
///
public string WriteResultFilename;
///
/// Data about the AssetBundleObject
///
public AssetBundleObjectInfo BundleObjectInfo;
///
/// The size of the data that needs to be preloaded for this File.
///
public int PreloadInfoSize;
///
/// The number of Mono scripts referenced by the File
///
public int MonoScriptCount;
///
/// The size of the Mono scripts referenced by the File
///
public ulong MonoScriptSize;
}
///
/// A representation of an object in an asset file.
///
[Serializable]
public class ObjectData
{
///
/// FileId of Object in Asset File
///
public long LocalIdentifierInFile;
///
/// Object name within the Asset
///
[SerializeField] internal string ObjectName;
///
/// Component name if AssetType is a MonoBehaviour or Component
///
[SerializeField] internal string ComponentName;
///
/// Type of Object
///
public AssetType AssetType;
///
/// The size of the file on disk.
///
public ulong SerializedSize;
///
/// The size of the streamed Asset.
///
public ulong StreamedSize;
///
/// References to other Objects
///
[SerializeField] internal List References = new List();
}
///
/// Identification of an Object within the same file
///
[Serializable]
internal class ObjectReference
{
public int AssetId;
public List ObjectIds;
}
///
/// Data store for Assets explicitly defined in an AssetBundle
///
[Serializable]
public class ExplicitAsset
{
///
/// The Asset Guid.
///
public string Guid;
///
/// The Asset path on disk
///
public string AssetPath;
///
/// Name used to identify the asset within the asset bundle containing it
///
public string InternalId;
///
/// Hash of the asset content
///
public Hash128 AssetHash;
///
/// Objects that consist of the overall asset
///
public List Objects = new List();
///
/// AssetType of the main Object for the Asset
///
public AssetType MainAssetType;
///
/// True if is a scene asset, else false
///
public bool IsScene => AssetPath.EndsWith(".unity", StringComparison.Ordinal);
///
/// Guid of the Addressable group this Asset entry was built using.
///
public string GroupGuid;
///
/// The Addressable address defined in the Addressable Group window for an Asset.
///
public string AddressableName;
///
/// Addressable labels for this asset entry.
///
[SerializeField]
public string[] Labels = Array.Empty();
///
/// The size of the file on disk.
///
public ulong SerializedSize;
///
/// The size of the streamed Asset.
///
public ulong StreamedSize;
///
/// The file that the Asset was added to
///
[SerializeReference]
public File File;
///
/// The AssetBundle that contains the asset
///
[SerializeReference]
public Bundle Bundle;
///
/// List of data from other Assets referenced by an Asset in the File
///
[SerializeReference]
public List InternalReferencedOtherAssets = new List();
///
/// List of explicit Assets referenced by this asset that are in the same AssetBundle
///
[SerializeReference]
public List InternalReferencedExplicitAssets = new List();
///
/// List of explicit Assets referenced by this asset that are in a different AssetBundle
///
[SerializeReference]
public List ExternallyReferencedAssets = new List();
///
/// List of Assets that reference this Asset
///
[SerializeReference]
internal List ReferencingAssets = new List();
}
///
/// Data store for implicit Asset references
///
[Serializable]
public class DataFromOtherAsset
{
///
/// The Guid of the Asset
///
public string AssetGuid;
///
/// The Asset path on disk
///
public string AssetPath;
///
/// The file that the Asset was added to
///
[SerializeReference]
public File File;
///
/// Objects that consist of the overall asset
///
public List Objects = new List();
///
/// AssetType of the main Object for the Asset
///
public AssetType MainAssetType;
///
/// True if is a scene asset, else false
///
public bool IsScene => AssetPath.EndsWith(".unity", StringComparison.Ordinal);
///
/// A list of Assets that reference this data
///
[SerializeReference]
public List ReferencingAssets = new List();
///
/// The number of Objects in the data
///
public int ObjectCount;
///
/// The size of the data on disk
///
public ulong SerializedSize;
///
/// The size of the streamed data
///
public ulong StreamedSize;
}
///
/// Data store for duplicated Implicit Asset information
///
[Serializable]
public class AssetDuplicationData
{
///
/// The Guid of the Asset with duplicates
///
public string AssetGuid;
///
/// A list of duplicated objects and the bundles that contain them.
///
public List DuplicatedObjects = new List();
}
///
/// Data store for duplicated Object information
///
[Serializable]
public class ObjectDuplicationData
{
///
/// The local identifier for an object.
///
public long LocalIdentifierInFile;
///
/// A list of bundles that include the referenced file.
///
[SerializeReference] public List IncludedInBundleFiles = new List();
}
}
///
/// Utility used to quickly reference data built with the build pipeline
///
public class LayoutLookupTables
{
///
/// The default AssetBundle name to the Bundle data map.
///
public Dictionary Bundles = new Dictionary();
///
/// File name to File data map.
///
public Dictionary Files = new Dictionary();
internal Dictionary FileToFileObjectData = new Dictionary();
///
/// Guid to ExplicitAsset data map.
///
public Dictionary GuidToExplicitAsset = new Dictionary();
///
/// Group name to Group data map.
///
public Dictionary GroupLookup = new Dictionary();
///
/// The remapped AssetBundle name to the Bundle data map
///
internal Dictionary FilenameToBundle = new Dictionary();
/// Maps used for lookups while building the BuildLayout
internal Dictionary> UsedImplicits = new Dictionary>();
internal Dictionary BundleNameToRequestOptions = new Dictionary();
internal Dictionary BundleNameToPreviousRequestOptions = new Dictionary();
internal Dictionary BundleNameToCatalogEntry = new Dictionary();
internal Dictionary GroupNameToBuildPath = new Dictionary();
internal Dictionary GuidToEntry = new Dictionary();
internal Dictionary AssetPathToTypeMap = new Dictionary();
}
internal class FileObjectData
{
// id's for internal explicit asset and implicit asset
public Dictionary InternalObjectIds = new Dictionary();
public Dictionary Objects = new Dictionary();
public void Add(ObjectIdentifier buildObjectIdentifier, BuildLayout.ObjectData layoutObject, int assetId, int objectIndex)
{
InternalObjectIds[buildObjectIdentifier] = (assetId, objectIndex);
Objects[layoutObject] = buildObjectIdentifier;
}
public bool TryGetObjectReferenceData(ObjectIdentifier obj, out (int, int) value)
{
if (!InternalObjectIds.TryGetValue(obj, out (int, int) data))
{
value = default;
return false;
}
value = data;
return true;
}
public bool TryGetObjectIdentifier(BuildLayout.ObjectData obj, out ObjectIdentifier objectIdOut)
{
if (!Objects.TryGetValue(obj, out objectIdOut))
{
objectIdOut = default;
return false;
}
return true;
}
}
}