using NUnit.Framework; using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text.RegularExpressions; using UnityEditor; using UnityEditor.Build.Content; using UnityEditor.Build.Pipeline; using UnityEditor.Build.Pipeline.Injector; using UnityEditor.Build.Pipeline.Interfaces; using UnityEditor.Build.Pipeline.Tasks; using UnityEditor.Build.Pipeline.Utilities; using UnityEditor.Build.Player; using UnityEditor.U2D; using UnityEngine; using UnityEngine.TestTools; using UnityEngine.U2D; namespace UnityEditor.Build.Pipeline.Tests { public class CalculateAssetDependencyTests { const string kTestAssetFolder = "Assets/TestAssets"; const string kTestAsset = "Assets/TestAssets/SpriteTexture32x32.png"; const string kSpriteTexture1Asset = "Assets/TestAssets/SpriteTexture1_32x32.png"; const string kSpriteTexture2Asset = "Assets/TestAssets/SpriteTexture2_32x32.png"; const string kSpriteAtlasAsset = "Assets/TestAssets/sadependencies.spriteAtlas"; SpritePackerMode m_PrevMode; class TestParams : TestBundleBuildParameters { bool m_DisableVisibleSubAssetRepresentations = false; public TestParams(bool disableVisibleSubAssetRepresentations) { m_DisableVisibleSubAssetRepresentations = disableVisibleSubAssetRepresentations; } public override bool DisableVisibleSubAssetRepresentations { get => m_DisableVisibleSubAssetRepresentations; } // Inputs public override bool UseCache { get; set; } public override BuildTarget Target { get => EditorUserBuildSettings.activeBuildTarget; } public override BuildTargetGroup Group { get => BuildTargetGroup.Unknown; } public override TypeDB ScriptInfo { get => null; } public override ContentBuildFlags ContentBuildFlags { get => ContentBuildFlags.None; } public override bool NonRecursiveDependencies { get => false; } #if !UNITY_2019_3_OR_NEWER public override string TempOutputFolder => ContentPipeline.kTempBuildPath; #endif public override BuildSettings GetContentBuildSettings() { return new BuildSettings { group = Group, target = Target, typeDB = ScriptInfo, buildFlags = ContentBuildFlags }; } } class TestContent : TestBundleBuildContent { public List TestAssets = new List(); // Inputs public override List Assets => TestAssets; } class TestDependencyData : TestDependencyDataBase { public Dictionary TestAssetInfo = new Dictionary(); public Dictionary TestAssetUsage = new Dictionary(); public Dictionary TestSceneInfo = new Dictionary(); public Dictionary TestSceneUsage = new Dictionary(); public Dictionary TestDependencyHash = new Dictionary(); // Inputs public override BuildUsageCache DependencyUsageCache => null; public override BuildUsageTagGlobal GlobalUsage => new BuildUsageTagGlobal(); // Outputs public override Dictionary AssetInfo => TestAssetInfo; public override Dictionary AssetUsage => TestAssetUsage; public override Dictionary SceneInfo => TestSceneInfo; public override Dictionary SceneUsage => TestSceneUsage; public override Dictionary DependencyHash => TestDependencyHash; } class TestExtendedAssetData : TestBundleExtendedAssetData { public Dictionary TestExtendedData = new Dictionary(); public override Dictionary ExtendedData => TestExtendedData; } static CalculateAssetDependencyData CreateDefaultBuildTask(List assets, bool disableVisibleSubassetRepresentations = false) { var task = new CalculateAssetDependencyData(); var testParams = new TestParams(disableVisibleSubassetRepresentations); var testContent = new TestContent { TestAssets = assets }; var testDepData = new TestDependencyData(); var testExtendedData = new TestExtendedAssetData(); var testObjDependencyData = new ObjectDependencyData(); IBuildContext context = new BuildContext(testParams, testContent, testDepData, testExtendedData, testObjDependencyData); ContextInjector.Inject(context, task); return task; } static void ExtractTestData(IBuildTask task, out TestExtendedAssetData extendedAssetData) { IBuildContext context = new BuildContext(); ContextInjector.Extract(context, task); extendedAssetData = (TestExtendedAssetData)context.GetContextObject(); } [SetUp] public void Setup() { m_PrevMode = EditorSettings.spritePackerMode; Directory.CreateDirectory(kTestAssetFolder); CreateTestSpriteTexture(kTestAsset, false); CreateTestSpriteTexture(kSpriteTexture1Asset, true); CreateTestSpriteTexture(kSpriteTexture2Asset, true); AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport | ImportAssetOptions.ForceUpdate); CreateSpriteAtlas(); } [TearDown] public void OneTimeTeardown() { AssetDatabase.DeleteAsset(kTestAssetFolder); File.Delete(kTestAssetFolder + ".meta"); EditorSettings.spritePackerMode = m_PrevMode; AssetDatabase.Refresh(); } static void CreateTestSpriteTexture(string texturePath, bool single) { var data = ImageConversion.EncodeToPNG(new Texture2D(32, 32)); File.WriteAllBytes(texturePath, data); AssetDatabase.ImportAsset(texturePath);//, ImportAssetOptions.ForceSynchronousImport | ImportAssetOptions.ForceUpdate); var importer = AssetImporter.GetAtPath(texturePath) as TextureImporter; importer.textureType = TextureImporterType.Sprite; if (single) { importer.spriteImportMode = SpriteImportMode.Single; } else { importer.spriteImportMode = SpriteImportMode.Multiple; importer.spritesheet = new[] { new SpriteMetaData { name = "WhiteTexture32x32_0", rect = new Rect(0, 19, 32, 13), alignment = 0, pivot = new Vector2(0.5f, 0.5f), border = new Vector4(0, 0, 0, 0) }, new SpriteMetaData { name = "WhiteTexture32x32_1", rect = new Rect(4, 19, 24, 11), alignment = 0, pivot = new Vector2(0.5f, 0.5f), border = new Vector4(0, 0, 0, 0) }, new SpriteMetaData { name = "WhiteTexture32x32_2", rect = new Rect(9, 5, 12, 7), alignment = 0, pivot = new Vector2(0.5f, 0.5f), border = new Vector4(0, 0, 0, 0) } }; } importer.SaveAndReimport(); } static void CreateSpriteAtlas() { var sa = new SpriteAtlas(); var targetObjects = new UnityEngine.Object[] { AssetDatabase.LoadAssetAtPath(kSpriteTexture1Asset), AssetDatabase.LoadAssetAtPath(kSpriteTexture2Asset) }; sa.Add(targetObjects); AssetDatabase.CreateAsset(sa, kSpriteAtlasAsset); AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport | ImportAssetOptions.ForceUpdate); } CalculateAssetDependencyData.TaskInput CreateDefaultInput() { CalculateAssetDependencyData.TaskInput input = new CalculateAssetDependencyData.TaskInput(); input.Target = EditorUserBuildSettings.activeBuildTarget; return input; } // Create a prefab and writes it to the specified path. The target file will have 2 objects in it: the GameObject and the Transform GUID CreateGameObject(string assetPath, string name = "go") { GameObject go = new GameObject(name); PrefabUtility.SaveAsPrefabAsset(go, assetPath); UnityEngine.Object.DestroyImmediate(go, false); string guidString = AssetDatabase.AssetPathToGUID(assetPath); GUID.TryParse(guidString, out GUID guid); return guid; } [Test] public void WhenAssetHasNoDependencies() { // Create an asset string assetPath = Path.Combine(kTestAssetFolder, "myPrefab.prefab"); GUID guid = CreateGameObject(assetPath); CalculateAssetDependencyData.TaskInput input = CreateDefaultInput(); input.Assets = new List() { guid }; CalculateAssetDependencyData.RunInternal(input, out CalculateAssetDependencyData.TaskOutput output); Assert.AreEqual(1, output.AssetResults.Length); Assert.AreEqual(guid, output.AssetResults[0].asset); Assert.AreEqual(2, output.AssetResults[0].assetInfo.includedObjects.Count); // GameObject and Transform Assert.AreEqual(2, output.AssetResults[0].objectDependencyInfo.Count); Assert.AreEqual(0, output.AssetResults[0].assetInfo.referencedObjects.Count); Assert.IsNull(output.AssetResults[0].spriteData); Assert.IsNull(output.AssetResults[0].extendedData); } [Test] public void WhenAssetDoesNotExist_AssetResultIsEmpty() { CalculateAssetDependencyData.TaskInput input = CreateDefaultInput(); input.Assets = new List() { GUID.Generate() }; CalculateAssetDependencyData.RunInternal(input, out CalculateAssetDependencyData.TaskOutput output); Assert.IsNull(output.AssetResults[0].extendedData); Assert.AreEqual(0, output.AssetResults[0].assetInfo.includedObjects.Count); Assert.AreEqual(0, output.AssetResults[0].objectDependencyInfo.Count); } [Test] public void WhenSomeAssetDataIsCached_CachedVersionIsUsed() { const int kCachedCount = 5; // Create 10 assets, import half of them, CalculateAssetDependencyData.TaskInput input = CreateDefaultInput(); string assetPath = Path.Combine(kTestAssetFolder, "myPrefab.prefab"); List allGUIDs = new List(); List cachedGUIDs = new List(); for (int i = 0; i < kCachedCount; i++) { GUID cachedGUID = CreateGameObject(Path.Combine(kTestAssetFolder, $"myPrefab{i * 2}.prefab"), $"go{i * 2}"); cachedGUIDs.Add(cachedGUID); allGUIDs.Add(cachedGUID); allGUIDs.Add(CreateGameObject(Path.Combine(kTestAssetFolder, $"myPrefab{i * 2 + 1}.prefab"), $"go{i * 2 + 1}")); } using (BuildCache cache = new BuildCache()) { cache.ClearCacheEntryMaps(); // needed if running multiple times input.BuildCache = cache; input.Assets = cachedGUIDs; CalculateAssetDependencyData.RunInternal(input, out CalculateAssetDependencyData.TaskOutput output); cache.SyncPendingSaves(); input.Assets = allGUIDs; CalculateAssetDependencyData.RunInternal(input, out CalculateAssetDependencyData.TaskOutput output2); Assert.AreEqual(output.AssetResults[0].assetInfo.includedObjects.Count, output2.AssetResults[0].assetInfo.includedObjects.Count); // GameObject and Transform Assert.AreEqual(output.AssetResults[0].objectDependencyInfo.Count, output2.AssetResults[0].objectDependencyInfo.Count); Assert.AreEqual(0, output.CachedAssetCount); Assert.AreEqual(kCachedCount, output2.CachedAssetCount); for (int i = 0; i < kCachedCount; i++) { bool seqEqual = Enumerable.SequenceEqual(output.AssetResults[i].assetInfo.includedObjects, output2.AssetResults[i * 2].assetInfo.includedObjects); Assert.IsTrue(seqEqual, "Included Objects where not the same when Cache was used."); Assert.AreEqual(output.AssetResults[i].objectDependencyInfo.Count, output2.AssetResults[i * 2].objectDependencyInfo.Count); for (int o = 0; o < output.AssetResults[i].objectDependencyInfo.Count; ++o) { var left = output.AssetResults[i].objectDependencyInfo[o]; bool found = false; foreach (ObjectDependencyInfo right in output2.AssetResults[i * 2].objectDependencyInfo) { if (right.Object == left.Object) { Assert.AreEqual(right.Dependencies.Count, left.Dependencies.Count, "Object dependency found between builds, but the dependencies are different count"); found = true; break; } } Assert.IsTrue(found, "Could not find matching object dependency between builds"); } } } } // Embedding this shader in code and only creating it when the test actually runs so it doesn't exist outside tests. string kTestShader = @"Shader ""Custom / NewSurfaceShader"" { Properties { _Color(""Color"", Color) = (1, 1, 1, 1) _MainTex(""Albedo (RGB)"", 2D) = ""white"" { } _Glossiness(""Smoothness"", Range(0, 1)) = 0.5 _Metallic(""Metallic"", Range(0, 1)) = 0.0 } SubShader { Tags { ""RenderType"" = ""Opaque"" } LOD 200 CGPROGRAM #pragma surface surf Standard fullforwardshadows #pragma target 3.0 #pragma shader_feature _ TEST_DEFINE sampler2D _MainTex; struct Input { float2 uv_MainTex; }; half _Glossiness; half _Metallic; fixed4 _Color; UNITY_INSTANCING_BUFFER_START(Props) UNITY_INSTANCING_BUFFER_END(Props) void surf(Input IN, inout SurfaceOutputStandard o) { // Albedo comes from a texture tinted by color fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; // Metallic and smoothness come from slider variables o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = c.a; } ENDCG } FallBack ""Diffuse"" } "; private void CreateTestShader(string path) { if (!File.Exists(path)) { File.WriteAllText(path, kTestShader); AssetDatabase.Refresh(); } } [Test] public void WhenObjectInfluencesReferencedObjectBuildTags_BuildUsageTagsAreAdded() { string testShaderPath = Path.Combine(kTestAssetFolder, "TestShader.shader"); CreateTestShader(testShaderPath); Shader shader = AssetDatabase.LoadAssetAtPath(testShaderPath); string shaderGUIDString = AssetDatabase.AssetPathToGUID(testShaderPath); GUID.TryParse(shaderGUIDString, out GUID shaderGUID); // Create a material that points to the test shader asset Material mat = new Material(shader); string matPath = Path.Combine(kTestAssetFolder, "testmat.mat"); AssetDatabase.CreateAsset(mat, matPath); string guidMatString = AssetDatabase.AssetPathToGUID(matPath); GUID.TryParse(guidMatString, out GUID matGUID); CalculateAssetDependencyData.TaskInput input = CreateDefaultInput(); input.Assets = new List() { matGUID }; CalculateAssetDependencyData.RunInternal(input, out CalculateAssetDependencyData.TaskOutput output); // this define should get added to the shader build usage tags mat.shaderKeywords = new string[] { "TEST_DEFINE" }; CalculateAssetDependencyData.TaskInput input2 = CreateDefaultInput(); input2.Assets = new List() { matGUID }; CalculateAssetDependencyData.RunInternal(input2, out CalculateAssetDependencyData.TaskOutput output2); var ids = output2.AssetResults[0].usageTags.GetObjectIdentifiers(); Assert.IsTrue(ids.Count((x) => x.guid == shaderGUID) == 1, "Shader is not in build usage tags"); Assert.AreNotEqual(output.AssetResults[0].usageTags.GetHashCode(), output2.AssetResults[0].usageTags.GetHashCode(), "Build usage tags were not affected by material keywords"); } static object[] SpriteTestCases = { #if UNITY_2020_1_OR_NEWER new object[] { SpritePackerMode.Disabled, "", false, false }, new object[] { SpritePackerMode.BuildTimeOnlyAtlas, "", true, true }, new object[] { SpritePackerMode.BuildTimeOnlyAtlas, "", false, false }, #else new object[] { SpritePackerMode.BuildTimeOnly, "SomeTag", true, true }, new object[] { SpritePackerMode.BuildTimeOnly, "", true, false }, new object[] { SpritePackerMode.AlwaysOn, "SomeTag", true, true }, new object[] { SpritePackerMode.AlwaysOn, "", true, false }, new object[] { SpritePackerMode.Disabled, "", true, false }, new object[] { SpritePackerMode.BuildTimeOnlyAtlas, "", true, true }, new object[] { SpritePackerMode.AlwaysOnAtlas, "", true, true }, new object[] { SpritePackerMode.AlwaysOnAtlas, "", false, false } #endif }; [TestCaseSource("SpriteTestCases")] [Test] public void WhenSpriteWithAtlas_SpriteImportDataCreated(SpritePackerMode spriteMode, string spritePackingTag, bool hasReferencingSpriteAtlas, bool expectedPacked) { TextureImporter importer = AssetImporter.GetAtPath(kTestAsset) as TextureImporter; importer.spritePackingTag = spritePackingTag; importer.SaveAndReimport(); if (hasReferencingSpriteAtlas) { var sa = new SpriteAtlas(); var targetObjects = new UnityEngine.Object[] { AssetDatabase.LoadAssetAtPath(kTestAsset) }; sa.Add(targetObjects); string saPath = Path.Combine(kTestAssetFolder, "sa.spriteAtlas"); AssetDatabase.CreateAsset(sa, saPath); AssetDatabase.Refresh(); } GUID.TryParse(AssetDatabase.AssetPathToGUID(kTestAsset), out GUID spriteGUID); CalculateAssetDependencyData.TaskInput input = CreateDefaultInput(); EditorSettings.spritePackerMode = spriteMode; SpriteAtlasUtility.PackAllAtlases(input.Target); input.Assets = new List() { spriteGUID }; CalculateAssetDependencyData.RunInternal(input, out CalculateAssetDependencyData.TaskOutput output); Assert.AreEqual(expectedPacked, output.AssetResults[0].spriteData.PackedSprite); } static object[] SpriteUtilityTestCases = { new object[] { SpritePackerMode.BuildTimeOnlyAtlas } }; [TestCaseSource("SpriteUtilityTestCases")] [Test] public void WhenSpriteWithAtlasUpdated_SpriteInfoUpdated(SpritePackerMode spriteMode) { var spriteAtlas = AssetDatabase.LoadAssetAtPath(kSpriteAtlasAsset); var oldSprites = SpriteAtlasExtensions.GetPackables(spriteAtlas); spriteAtlas.Remove(oldSprites); List sprites = new List(); sprites.Add(AssetDatabase.LoadAssetAtPath(kSpriteTexture1Asset)); sprites.Add(AssetDatabase.LoadAssetAtPath(kSpriteTexture2Asset)); SpriteAtlasExtensions.Add(spriteAtlas, sprites.ToArray()); GUID.TryParse(AssetDatabase.AssetPathToGUID(kSpriteAtlasAsset), out GUID spriteGUID); BuildCacheUtility.ClearCacheHashes(); CalculateAssetDependencyData.TaskInput input = CreateDefaultInput(); input.BuildCache = new BuildCache(); input.NonRecursiveDependencies = true; EditorSettings.spritePackerMode = spriteMode; SpriteAtlasUtility.PackAllAtlases(input.Target); input.Assets = new List() { spriteGUID }; CalculateAssetDependencyData.RunInternal(input, out CalculateAssetDependencyData.TaskOutput output); Assert.AreEqual(3, output.AssetResults[0].assetInfo.referencedObjects.Count); spriteAtlas = AssetDatabase.LoadAssetAtPath(kSpriteAtlasAsset); oldSprites = SpriteAtlasExtensions.GetPackables(spriteAtlas); spriteAtlas.Remove(oldSprites); sprites = new List(); sprites.Add(AssetDatabase.LoadAssetAtPath(kSpriteTexture1Asset)); SpriteAtlasExtensions.Add(spriteAtlas, sprites.ToArray()); SpriteAtlasUtility.PackAllAtlases(input.Target); CalculateAssetDependencyData.RunInternal(input, out CalculateAssetDependencyData.TaskOutput output2); Assert.AreEqual(2, output2.AssetResults[0].assetInfo.referencedObjects.Count); } #if !UNITY_2020_2_OR_NEWER // This test is only important for going through AssetDatabase's LoadAllAssetRepresentationsAtPath // in 2020.2 and newer we have a new build api that handles nulls natively and this no longer applies. class NullLoadRepresentationFake : CalculateAssetDependencyHooks { public override UnityEngine.Object[] LoadAllAssetRepresentationsAtPath(string assetPath) { return new UnityEngine.Object[] { null }; } } [Test] public void WhenAssetHasANullRepresentation_LogsWarning() { // Create an asset string assetPath = Path.Combine(kTestAssetFolder, "myPrefab.prefab"); GUID guid = CreateGameObject(assetPath); CalculateAssetDependencyData.TaskInput input = CreateDefaultInput(); input.Assets = new List() { guid }; input.EngineHooks = new NullLoadRepresentationFake(); LogAssert.Expect(LogType.Warning, new Regex(".+It will not be included in the build")); CalculateAssetDependencyData.RunInternal(input, out CalculateAssetDependencyData.TaskOutput output); Assert.AreEqual(guid, output.AssetResults[0].asset); Assert.AreEqual(2, output.AssetResults[0].assetInfo.includedObjects.Count); // GameObject and Transform Assert.AreEqual(0, output.AssetResults[0].assetInfo.referencedObjects.Count); } #endif [Test] public void WhenAssetHasMultipleRepresentations_ExtendedDataContainsAllButMainAsset() { const int kExtraRepresentations = 2; string assetPath = Path.Combine(kTestAssetFolder, "myPrefab.asset"); Material mat = new Material(Shader.Find("Transparent/Diffuse")); AssetDatabase.CreateAsset(mat, assetPath); for (int i = 0; i < kExtraRepresentations; i++) AssetDatabase.AddObjectToAsset(new Material(Shader.Find("Transparent/Diffuse")), assetPath); AssetDatabase.SaveAssets(); GUID guid = new GUID(AssetDatabase.AssetPathToGUID(assetPath)); CalculateAssetDependencyData.TaskInput input = CreateDefaultInput(); input.Assets = new List() { guid }; CalculateAssetDependencyData.RunInternal(input, out CalculateAssetDependencyData.TaskOutput output); ObjectIdentifier[] allObjIDs = ContentBuildInterface.GetPlayerObjectIdentifiersInAsset(guid, EditorUserBuildSettings.activeBuildTarget); HashSet expectedReps = new HashSet(); for (int i = 1; i < allObjIDs.Length; i++) expectedReps.Add(allObjIDs[i]); Assert.AreEqual(kExtraRepresentations, output.AssetResults[0].extendedData.Representations.Count); Assert.AreEqual(kExtraRepresentations, expectedReps.Count); foreach (var id in output.AssetResults[0].extendedData.Representations) Assert.IsTrue(expectedReps.Contains(id)); } [Test] public void WhenExplicitSpriteAndAtlas_AtlasOnlyReferencesSprites() { GUID spriteAtlasGuid = new GUID(AssetDatabase.AssetPathToGUID(kSpriteAtlasAsset)); GUID sprite1Guid = new GUID(AssetDatabase.AssetPathToGUID(kSpriteTexture1Asset)); GUID sprite2Guid = new GUID(AssetDatabase.AssetPathToGUID(kSpriteTexture2Asset)); EditorSettings.spritePackerMode = SpritePackerMode.BuildTimeOnlyAtlas; CalculateAssetDependencyData.TaskInput input = CreateDefaultInput(); SpriteAtlasUtility.PackAllAtlases(input.Target); input.Assets = new List() { spriteAtlasGuid, sprite1Guid, sprite2Guid }; CalculateAssetDependencyData.RunInternal(input, out CalculateAssetDependencyData.TaskOutput output); Assert.AreEqual(3, output.AssetResults[0].assetInfo.referencedObjects.Count); } class TestProgressTracker : IProgressTracker { int count = 0; public int TaskCount { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } public float Progress => throw new NotImplementedException(); public bool UpdateInfo(string taskInfo) { return count++ > 0; } public bool UpdateTask(string taskTitle) { throw new NotImplementedException(); } } [Test] public void WhenCanceledThroughProgressTracker_ReturnsCanceled() { string assetPath1 = Path.Combine(kTestAssetFolder, "myPrefab1.prefab"); string assetPath2 = Path.Combine(kTestAssetFolder, "myPrefab2.prefab"); CalculateAssetDependencyData.TaskInput input = CreateDefaultInput(); input.Assets = new List() { CreateGameObject(assetPath1), CreateGameObject(assetPath2) }; input.ProgressTracker = new TestProgressTracker(); ReturnCode code = CalculateAssetDependencyData.RunInternal(input, out CalculateAssetDependencyData.TaskOutput output); Assert.AreEqual(null, output.AssetResults[1].assetInfo); Assert.AreEqual(ReturnCode.Canceled, code); } [Test] public void TaskIsRun_WhenAssetHasNoMultipleRepresentations_ExtendedDataIsEmpty() { string assetPath = Path.Combine(kTestAssetFolder, "myPrefab.prefab"); GUID guid = CreateGameObject(assetPath); bool disableVisibleSubAssetRepresentations = false; CalculateAssetDependencyData buildTask = CreateDefaultBuildTask(new List() { guid }, disableVisibleSubAssetRepresentations); buildTask.Run(); ExtractTestData(buildTask, out TestExtendedAssetData extendedAssetData); Assert.AreEqual(0, extendedAssetData.ExtendedData.Count); } [Test] public void TaskIsRun_WhenAssetHasMultipleRepresentations_ExtendedDataContainsEntryForAsset() { string assetPath = Path.Combine(kTestAssetFolder, "myPrefab.asset"); Material mat = new Material(Shader.Find("Transparent/Diffuse")); AssetDatabase.CreateAsset(mat, assetPath); AssetDatabase.AddObjectToAsset(new Material(Shader.Find("Transparent/Diffuse")), assetPath); AssetDatabase.SaveAssets(); string guidString = AssetDatabase.AssetPathToGUID(assetPath); GUID.TryParse(guidString, out GUID guid); bool disableVisibleSubAssetRepresentations = false; CalculateAssetDependencyData buildTask = CreateDefaultBuildTask(new List() { guid }, disableVisibleSubAssetRepresentations); buildTask.Run(); ExtractTestData(buildTask, out TestExtendedAssetData extendedAssetData); Assert.AreEqual(1, extendedAssetData.ExtendedData.Count); Assert.IsTrue(extendedAssetData.ExtendedData.ContainsKey(guid)); } [Test] public void TaskIsRun_WhenAssetHasMultipleRepresentations_AndDisableVisibleSubAssetRepresentations_ExtendedDataIsEmpty() { string assetPath = Path.Combine(kTestAssetFolder, "myPrefab.asset"); Material mat = new Material(Shader.Find("Transparent/Diffuse")); AssetDatabase.CreateAsset(mat, assetPath); AssetDatabase.AddObjectToAsset(new Material(Shader.Find("Transparent/Diffuse")), assetPath); AssetDatabase.SaveAssets(); string guidString = AssetDatabase.AssetPathToGUID(assetPath); GUID.TryParse(guidString, out GUID guid); bool disableVisibleSubAssetRepresentations = true; CalculateAssetDependencyData buildTask = CreateDefaultBuildTask(new List() { guid }, disableVisibleSubAssetRepresentations); buildTask.Run(); ExtractTestData(buildTask, out TestExtendedAssetData extendedAssetData); Assert.AreEqual(0, extendedAssetData.ExtendedData.Count); } } }