ZoeAppClass/Library/PackageCache/com.unity.scriptablebuildpi.../Editor/Tasks/GenerateBundleCommands.cs

203 lines
8.4 KiB
C#

using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor.Build.Content;
using UnityEditor.Build.Pipeline.Injector;
using UnityEditor.Build.Pipeline.Interfaces;
using UnityEditor.Build.Pipeline.Utilities;
using UnityEditor.Build.Pipeline.WriteTypes;
using UnityEditor.Build.Utilities;
#if !UNITY_2019_1_OR_NEWER
using System;
using UnityEngine;
#endif
namespace UnityEditor.Build.Pipeline.Tasks
{
public class GenerateBundleCommands : IBuildTask
{
public int Version { get { return 1; } }
#pragma warning disable 649
[InjectContext(ContextUsage.In)]
IBundleBuildContent m_BuildContent;
[InjectContext(ContextUsage.In)]
IDependencyData m_DependencyData;
[InjectContext]
IBundleWriteData m_WriteData;
[InjectContext(ContextUsage.In)]
IDeterministicIdentifiers m_PackingMethod;
#pragma warning restore 649
public ReturnCode Run()
{
foreach (var bundlePair in m_BuildContent.BundleLayout)
{
if (ValidationMethods.ValidAssetBundle(bundlePair.Value))
{
// Use generated internalName here as we could have an empty asset bundle used for raw object storage (See CreateStandardShadersBundle)
var internalName = string.Format(CommonStrings.AssetBundleNameFormat, m_PackingMethod.GenerateInternalFileName(bundlePair.Key));
CreateAssetBundleCommand(bundlePair.Key, internalName, bundlePair.Value);
}
else if (ValidationMethods.ValidSceneBundle(bundlePair.Value))
{
CreateSceneBundleCommand(bundlePair.Key, m_WriteData.AssetToFiles[bundlePair.Value[0]][0], bundlePair.Value[0], bundlePair.Value);
for (int i = 1; i < bundlePair.Value.Count; ++i)
CreateSceneDataCommand(m_WriteData.AssetToFiles[bundlePair.Value[i]][0], bundlePair.Value[i]);
}
}
return ReturnCode.Success;
}
static WriteCommand CreateWriteCommand(string internalName, List<ObjectIdentifier> objects, IDeterministicIdentifiers packingMethod)
{
var command = new WriteCommand();
command.internalName = internalName;
command.fileName = Path.GetFileName(internalName);
command.serializeObjects = objects.Select(x => new SerializationInfo
{
serializationObject = x,
serializationIndex = packingMethod.SerializationIndexFromObjectIdentifier(x)
}).ToList();
return command;
}
void CreateAssetBundleCommand(string bundleName, string internalName, List<GUID> assets)
{
var abOp = new AssetBundleWriteOperation();
var fileObjects = m_WriteData.FileToObjects[internalName];
abOp.Command = CreateWriteCommand(internalName, fileObjects, m_PackingMethod);
abOp.UsageSet = new BuildUsageTagSet();
m_WriteData.FileToUsageSet.Add(internalName, abOp.UsageSet);
abOp.ReferenceMap = new BuildReferenceMap();
abOp.ReferenceMap.AddMappings(internalName, abOp.Command.serializeObjects.ToArray());
m_WriteData.FileToReferenceMap.Add(internalName, abOp.ReferenceMap);
{
abOp.Info = new AssetBundleInfo();
abOp.Info.bundleName = bundleName;
abOp.Info.bundleAssets = assets.Select(x => m_DependencyData.AssetInfo[x]).ToList();
foreach (var loadInfo in abOp.Info.bundleAssets)
loadInfo.address = m_BuildContent.Addresses[loadInfo.asset];
}
m_WriteData.WriteOperations.Add(abOp);
}
#if !UNITY_2019_1_OR_NEWER
static int GetSortIndex(Type type)
{
// ContentBuildInterface.GetTypeForObjects returns null for some MonoBehaviours, this will fix it until the API is fixed.
if (type == null)
return Int32.MaxValue - 3;
if (type == typeof(MonoScript))
return Int32.MinValue;
if (typeof(ScriptableObject).IsAssignableFrom(type))
return Int32.MaxValue - 4;
if (typeof(MonoBehaviour).IsAssignableFrom(type))
return Int32.MaxValue - 3;
if (typeof(TerrainData).IsAssignableFrom(type))
return Int32.MaxValue - 2;
return BitConverter.ToInt32(HashingMethods.Calculate(type.Name).ToBytes(), 0);
}
struct SortObject
{
public ObjectIdentifier objectId;
public int sortIndex;
}
static List<ObjectIdentifier> GetSortedSceneObjectIdentifiers(List<ObjectIdentifier> objects)
{
var types = new List<Type>(ContentBuildInterface.GetTypeForObjects(objects.ToArray()));
var sortedObjects = new List<SortObject>();
for (int i = 0; i < objects.Count; i++)
sortedObjects.Add(new SortObject { sortIndex = GetSortIndex(types[i]), objectId = objects[i] });
return sortedObjects.OrderBy(x => x.sortIndex).Select(x => x.objectId).ToList();
}
#endif
void CreateSceneBundleCommand(string bundleName, string internalName, GUID asset, List<GUID> assets)
{
var sbOp = new SceneBundleWriteOperation();
var fileObjects = m_WriteData.FileToObjects[internalName];
#if !UNITY_2019_1_OR_NEWER
// ContentBuildInterface.PrepareScene was not returning stable sorted references, causing a indeterminism and loading errors in some cases
// Add correct sorting here until patch lands to fix the API.
fileObjects = GetSortedSceneObjectIdentifiers(fileObjects);
#endif
sbOp.Command = CreateWriteCommand(internalName, fileObjects, new LinearPackedIdentifiers(3)); // Start at 3: PreloadData = 1, AssetBundle = 2
sbOp.UsageSet = new BuildUsageTagSet();
m_WriteData.FileToUsageSet.Add(internalName, sbOp.UsageSet);
sbOp.ReferenceMap = new BuildReferenceMap();
m_WriteData.FileToReferenceMap.Add(internalName, sbOp.ReferenceMap);
var sceneInfo = m_DependencyData.SceneInfo[asset];
sbOp.Scene = sceneInfo.scene;
#if !UNITY_2019_3_OR_NEWER
sbOp.ProcessedScene = sceneInfo.processedScene;
#endif
{
sbOp.PreloadInfo = new PreloadInfo { preloadObjects = sceneInfo.referencedObjects.Where(x => !fileObjects.Contains(x)).ToList() };
}
{
sbOp.Info = new SceneBundleInfo();
sbOp.Info.bundleName = bundleName;
sbOp.Info.bundleScenes = assets.Select(x => new SceneLoadInfo
{
asset = x,
internalName = Path.GetFileNameWithoutExtension(m_WriteData.AssetToFiles[x][0]),
address = m_BuildContent.Addresses[x]
}).ToList();
}
m_WriteData.WriteOperations.Add(sbOp);
}
void CreateSceneDataCommand(string internalName, GUID asset)
{
var sdOp = new SceneDataWriteOperation();
var fileObjects = m_WriteData.FileToObjects[internalName];
#if !UNITY_2019_1_OR_NEWER
// ContentBuildInterface.PrepareScene was not returning stable sorted references, causing a indeterminism and loading errors in some cases
// Add correct sorting here until patch lands to fix the API.
fileObjects = GetSortedSceneObjectIdentifiers(fileObjects);
#endif
sdOp.Command = CreateWriteCommand(internalName, fileObjects, new LinearPackedIdentifiers(2)); // Start at 2: PreloadData = 1
sdOp.UsageSet = new BuildUsageTagSet();
m_WriteData.FileToUsageSet.Add(internalName, sdOp.UsageSet);
sdOp.ReferenceMap = new BuildReferenceMap();
m_WriteData.FileToReferenceMap.Add(internalName, sdOp.ReferenceMap);
var sceneInfo = m_DependencyData.SceneInfo[asset];
sdOp.Scene = sceneInfo.scene;
#if !UNITY_2019_3_OR_NEWER
sdOp.ProcessedScene = sceneInfo.processedScene;
#endif
{
sdOp.PreloadInfo = new PreloadInfo();
sdOp.PreloadInfo.preloadObjects = sceneInfo.referencedObjects.Where(x => !fileObjects.Contains(x)).ToList();
}
m_WriteData.WriteOperations.Add(sdOp);
}
}
}