diff --git a/CHANGELOG.md b/CHANGELOG.md index c3fb0f1..fd7f053 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,12 @@ All notable changes to this package will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [1.21.25] - 2024-10-18 +- Fixed issue where more than 2 Scriptable Objects are nested and Compatability Pipeline is used to build. + ## [1.21.24] - 2024-06-26 -Fix issue where build fails when not installed server platform is selected in the Build Settings Window -Fixed issue where total size of all bundles changes when updating the same Addressable Groups build. +- Fix issue where build fails when not installed server platform is selected in the Build Settings Window +- Fixed issue where total size of all bundles changes when updating the same Addressable Groups build. ## [1.21.23] - 2024-05-03 - Fixed issue where SpriteAtlas addressable bundle size is doubled if previous build cache is not cleared diff --git a/Editor/CompatibilityBuildPipeline.cs b/Editor/CompatibilityBuildPipeline.cs index 53413a5..f354297 100644 --- a/Editor/CompatibilityBuildPipeline.cs +++ b/Editor/CompatibilityBuildPipeline.cs @@ -87,6 +87,11 @@ internal static CompatibilityAssetBundleManifest BuildAssetBundles_Internal(stri if ((options & BuildAssetBundleOptions.DisableWriteTypeTree) != 0) parameters.ContentBuildFlags |= ContentBuildFlags.DisableWriteTypeTree; +#if BUILD_OPTIONS_RECURSE_DEPENDENCIES_2022_3 || BUILD_OPTIONS_RECURSE_DEPENDENCIES_2023_3 || UNITY_6000_0_OR_NEWER + if ((options & BuildAssetBundleOptions.RecurseDependencies) != 0) + parameters.NonRecursiveDependencies = false; +#endif + IBundleBuildResults results; ReturnCode exitCode = ContentPipeline.BuildAssetBundles(parameters, content, out results); if (exitCode < ReturnCode.Success) diff --git a/Editor/ContentPipeline.cs b/Editor/ContentPipeline.cs index bb4d2be..738e68b 100644 --- a/Editor/ContentPipeline.cs +++ b/Editor/ContentPipeline.cs @@ -204,13 +204,20 @@ internal static bool CanBuildPlayer(BuildTarget target, BuildTargetGroup targetG if (buildWindowExtension == null) return false; + #if STANDALONE_BUILD_ERROR_CHECK_2022_3 || STANDALONE_BUILD_ERROR_CHECK_2021_3 // Special case. DesktopStandaloneBuildWindowExtension.EnabledBuildButton() checks for the currently selected (not active) build target in the window. if (buildWindowExtension is DesktopStandaloneBuildWindowExtension standaloneExtension) { var namedBuildTarget = NamedBuildTarget.FromActiveSettings(target); string errorMsg = standaloneExtension.GetBuildPlayerError(namedBuildTarget); - return string.IsNullOrEmpty(errorMsg); + + if (!string.IsNullOrEmpty(errorMsg)) + { + BuildLogger.LogError(errorMsg); + return false; + } + return true; } #endif return buildWindowExtension.EnabledBuildButton(); diff --git a/Editor/Unity.ScriptableBuildPipeline.Editor.asmdef b/Editor/Unity.ScriptableBuildPipeline.Editor.asmdef index b703f52..ff9ac67 100644 --- a/Editor/Unity.ScriptableBuildPipeline.Editor.asmdef +++ b/Editor/Unity.ScriptableBuildPipeline.Editor.asmdef @@ -32,13 +32,13 @@ }, { "name": "Unity", - "expression": "[2022.3.30f1,2023)", - "define": "STANDALONE_BUILD_ERROR_CHECK_2022_3" + "expression": "[2022.3.21f1,2023.1)", + "define": "BUILD_OPTIONS_RECURSE_DEPENDENCIES_2022_3" }, { "name": "Unity", - "expression": "[2021.3.39f1,2022)", - "define": "STANDALONE_BUILD_ERROR_CHECK_2021_3" + "expression": "2023.3.0b1", + "define": "BUILD_OPTIONS_RECURSE_DEPENDENCIES_2023_3" } ], "noEngineReferences": false diff --git a/Tests/Editor/BundleDependencyTests.cs b/Tests/Editor/BundleDependencyTests.cs new file mode 100644 index 0000000..85fb86a --- /dev/null +++ b/Tests/Editor/BundleDependencyTests.cs @@ -0,0 +1,149 @@ +using UnityEngine; +using UnityEngine.Build.Pipeline; +using Unity.ScriptableBuildPipelineTests; +using NUnit.Framework; +using System.IO; +using System.Linq; + +namespace UnityEditor.Build.Pipeline.Tests +{ + [TestFixture] + class BundleDependencyTests + { + const string k_TmpAssetPath = "Assets/TempAssets"; + const string k_BuildFolder = "TestBuild"; + const int k_CntPrefabChain = 5; + + [OneTimeSetUp] + public void Setup() + { + Directory.CreateDirectory(k_TmpAssetPath); + + // Create scenario similar to BPSBP-740 + + var prefabRoots = new GameObject[k_CntPrefabChain]; + + for (int i = k_CntPrefabChain - 1; i >= 0; i--) + { + var gameObject = new GameObject(); + var mb = gameObject.AddComponent(); + var prefabPath = $"{k_TmpAssetPath}/prefab{i}.prefab"; + + + if (i != k_CntPrefabChain - 1) + { + // Point to the next prefab in the chain + mb.Reference = prefabRoots[i+1]; + Assert.IsNotNull(mb.Reference); + } + else + { + mb.Reference = gameObject; // Pointer to self, like in the original repro + } + + prefabRoots[i] = PrefabUtility.SaveAsPrefabAsset(gameObject, prefabPath); + AssetDatabase.ImportAsset(prefabPath, ImportAssetOptions.ForceSynchronousImport & ImportAssetOptions.ForceUpdate); + } + } + + [OneTimeTearDown] + public void Cleanup() + { + if (Directory.Exists(k_BuildFolder)) + Directory.Delete(k_BuildFolder, true); + + AssetDatabase.DeleteAsset(k_TmpAssetPath); + } + + static CompatibilityAssetBundleManifest BuildPrefabBundles(bool recurseDeps) + { + // Put each prefab into its own AssetBundle + var bundleDefinitions = new AssetBundleBuild[k_CntPrefabChain]; + for (int i = 0; i < bundleDefinitions.Length; i++) + { + bundleDefinitions[i].assetBundleName = $"{i}"; + bundleDefinitions[i].assetNames = new string[] { $"{k_TmpAssetPath}/prefab{i}.prefab" }; + }; + + if (Directory.Exists(k_BuildFolder)) + Directory.Delete(k_BuildFolder, true); + + Directory.CreateDirectory(k_BuildFolder); + + // Todo, confirm that the NonRecursive Mode is enabled, the test assumes that it is and i think that is the default but its not exposed in this API + + var manifest = default(CompatibilityAssetBundleManifest); + +#if BUILD_OPTIONS_RECURSE_DEPENDENCIES_2022_3 || BUILD_OPTIONS_RECURSE_DEPENDENCIES_2023_3 || UNITY_6000_0_OR_NEWER + if (recurseDeps) + { + manifest = CompatibilityBuildPipeline.BuildAssetBundles( + k_BuildFolder, + bundleDefinitions, + BuildAssetBundleOptions.AppendHashToAssetBundleName | BuildAssetBundleOptions.RecurseDependencies, + EditorUserBuildSettings.activeBuildTarget); + } + else +#endif + { + manifest = CompatibilityBuildPipeline.BuildAssetBundles( + k_BuildFolder, + bundleDefinitions, + BuildAssetBundleOptions.AppendHashToAssetBundleName, + EditorUserBuildSettings.activeBuildTarget); + } + + Assert.IsNotNull(manifest); + + return manifest; + } + +#if BUILD_OPTIONS_RECURSE_DEPENDENCIES_2022_3 || BUILD_OPTIONS_RECURSE_DEPENDENCIES_2023_3 || UNITY_6000_0_OR_NEWER + [Test, Description("BPSBP-737 / ADDR-3262")] + public void MonoScriptsAreNotNullInChainedBundles() + { + // Note: Test could also do variations, with MonoScript bundle enabled, maybe also NonRecursive=false + CompatibilityAssetBundleManifest manifest = BuildPrefabBundles(true); + + string prefabBundleMatch = "*_*"; // Match bundle names like 0_f5b4234bbd5a5a599bd740802cc6f9cf and ignore other build output + + // All the prefabs as loaded from the assetbundles should have valid MonoBehaviour with non-null reference, matching + // how we created them in the project. + var builtBundlePaths = Directory.EnumerateFiles(k_BuildFolder, prefabBundleMatch, SearchOption.TopDirectoryOnly).ToArray(); + LoadBundlesAndCheckMonoScript(builtBundlePaths); + } +#endif + + static void LoadBundlesAndCheckMonoScript(string[] bundleNames) + { + var bundleCount = bundleNames.Length; + var bundles = new AssetBundle[bundleCount]; + for (int i = 0; i < bundleCount; i++) + { + bundles[i] = AssetBundle.LoadFromFile(bundleNames[i]); + } + + try + { + for (int i = 0; i < bundleCount; i++) + { + if (bundles[i].name == "UnityMonoScripts.bundle") + continue; + + var prefab = bundles[i].LoadAllAssets()[0]; + var monoBehaviour = prefab.GetComponent(); + + Assert.IsNotNull(monoBehaviour, "Missing MonoScript or MonoBehaviourWithReference on " + bundleNames[i]); + + var monoScript = MonoScript.FromMonoBehaviour(monoBehaviour); + Assert.IsNotNull(monoScript); + } + } + finally + { + for (int i = 0; i < bundleCount; i++) + bundles[i].Unload(true); + } + } + } +} diff --git a/Tests/Editor/BundleDependencyTests.cs.meta b/Tests/Editor/BundleDependencyTests.cs.meta new file mode 100644 index 0000000..7a9ca23 --- /dev/null +++ b/Tests/Editor/BundleDependencyTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1c9bc2bb27e050d47aa4770a81642c8e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/Editor/Unity.ScriptableBuildPipeline.Editor.Tests.asmdef b/Tests/Editor/Unity.ScriptableBuildPipeline.Editor.Tests.asmdef index ecc2df2..eee208b 100644 --- a/Tests/Editor/Unity.ScriptableBuildPipeline.Editor.Tests.asmdef +++ b/Tests/Editor/Unity.ScriptableBuildPipeline.Editor.Tests.asmdef @@ -1,20 +1,29 @@ { "name": "Unity.ScriptableBuildPipeline.Editor.Tests", + "rootNamespace": "", "references": [ "Unity.ScriptableBuildPipeline.Editor", "Unity.ScriptableBuildPipeline", "Unity.PerformanceTesting", - "Unity.PerformanceTesting.Editor" - ], - "optionalUnityReferences": [ - "TestAssemblies" + "Unity.PerformanceTesting.Editor", + "UnityEngine.TestRunner", + "UnityEditor.TestRunner", + "ScriptableBuildPipelineTests" ], "includePlatforms": [ "Editor" ], "excludePlatforms": [], "allowUnsafeCode": true, - "defineConstraints": [ + "overrideReferences": true, + "precompiledReferences": [ + "nunit.framework.dll" + ], + "autoReferenced": false, + "defineConstraints": [ + "UNITY_INCLUDE_TESTS", "UNITY_INCLUDE_TESTS" - ] + ], + "versionDefines": [], + "noEngineReferences": false } \ No newline at end of file diff --git a/Tests/TestAssets.meta b/Tests/TestAssets.meta new file mode 100644 index 0000000..54ef195 --- /dev/null +++ b/Tests/TestAssets.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 43ed56232a7649647a25c24e3047a8dd +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/TestAssets/MonoBehaviourWithReference.cs b/Tests/TestAssets/MonoBehaviourWithReference.cs new file mode 100644 index 0000000..927257f --- /dev/null +++ b/Tests/TestAssets/MonoBehaviourWithReference.cs @@ -0,0 +1,11 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace Unity.ScriptableBuildPipelineTests +{ + public class MonoBehaviourWithReference : MonoBehaviour + { + public Object Reference; + } +} diff --git a/Tests/TestAssets/MonoBehaviourWithReference.cs.meta b/Tests/TestAssets/MonoBehaviourWithReference.cs.meta new file mode 100644 index 0000000..830cf63 --- /dev/null +++ b/Tests/TestAssets/MonoBehaviourWithReference.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c38171bd3350dba4da046a0e22442c01 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/TestAssets/ScriptableBuildPipelineTests.asmdef b/Tests/TestAssets/ScriptableBuildPipelineTests.asmdef new file mode 100644 index 0000000..02dddd8 --- /dev/null +++ b/Tests/TestAssets/ScriptableBuildPipelineTests.asmdef @@ -0,0 +1,9 @@ +{ + "name": "ScriptableBuildPipelineTests", + "optionalUnityReferences": [ + "TestAssemblies" + ], + "defineConstraints": [ + "UNITY_INCLUDE_TESTS" + ] +} diff --git a/Tests/TestAssets/ScriptableBuildPipelineTests.asmdef.meta b/Tests/TestAssets/ScriptableBuildPipelineTests.asmdef.meta new file mode 100644 index 0000000..3284158 --- /dev/null +++ b/Tests/TestAssets/ScriptableBuildPipelineTests.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: b3d0096afb8b48f4c88de2672cc76462 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/ValidationExceptions.json b/ValidationExceptions.json index a34d91b..133d6ae 100644 --- a/ValidationExceptions.json +++ b/ValidationExceptions.json @@ -4,7 +4,7 @@ { "ValidationTest": "API Validation", "ExceptionError": "", - "PackageVersion": "1.21.24" + "PackageVersion": "1.21.25" } ] } diff --git a/package.json b/package.json index 2c75ed7..664f532 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "com.unity.scriptablebuildpipeline", "displayName": "Scriptable Build Pipeline", - "version": "1.21.24", + "version": "1.21.25", "unity": "2019.4", "description": "The Scriptable Build Pipeline moves the asset bundle build pipeline to C#. Use the pre-defined build flows, or create your own using the divided up APIs. This system improves build time, fixes incremental build, and provides greater flexibility.", "keywords": [ @@ -14,15 +14,15 @@ ], "dependencies": {}, "_upm": { - "changelog": "Fix issue where build fails when not installed server platform is selected in the Build Settings Window\nFixed issue where total size of all bundles changes when updating the same Addressable Groups build." + "changelog": "- Fixed issue where more than 2 Scriptable Objects are nested and Compatability Pipeline is used to build." }, "upmCi": { - "footprint": "8cb47ea3786fb5bcc125c400a6f42a30e817a155" + "footprint": "f72bee75ef137f73673bff7c5b2b8938cb684e8c" }, "documentationUrl": "https://docs.unity3d.com/Packages/com.unity.scriptablebuildpipeline@1.21/manual/index.html", "repository": { "url": "https://github.cds.internal.unity3d.com/unity/Addressables.git", "type": "git", - "revision": "dc29b7795799cb70cc16868d4f07961052a3b033" + "revision": "10cb5465c9d5eb7ae72cfc3c120116131c3852f0" } }