From ad983354c74daece3ed2fd9c904139c678f064f3 Mon Sep 17 00:00:00 2001 From: yellowisher Date: Sat, 9 Nov 2024 22:16:37 +0900 Subject: [PATCH 1/3] Make Instantiate() revert dirty state of prefab --- .../PrefabComponentProvider.cs | 2 + .../VContainer/Runtime/Unity/LifetimeScope.cs | 2 + .../Unity/ObjectResolverUnityExtensions.cs | 38 +++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/VContainer/Assets/VContainer/Runtime/Unity/InstanceProviders/PrefabComponentProvider.cs b/VContainer/Assets/VContainer/Runtime/Unity/InstanceProviders/PrefabComponentProvider.cs index 82beb168..8a4e0422 100644 --- a/VContainer/Assets/VContainer/Runtime/Unity/InstanceProviders/PrefabComponentProvider.cs +++ b/VContainer/Assets/VContainer/Runtime/Unity/InstanceProviders/PrefabComponentProvider.cs @@ -29,6 +29,8 @@ public object SpawnInstance(IObjectResolver resolver) var parent = destination.GetParent(resolver); var wasActive = prefab.gameObject.activeSelf; + using var dirtyScope = new ObjectResolverUnityExtensions.PrefabDirtyScope(prefab.gameObject); + if (wasActive) { prefab.gameObject.SetActive(false); diff --git a/VContainer/Assets/VContainer/Runtime/Unity/LifetimeScope.cs b/VContainer/Assets/VContainer/Runtime/Unity/LifetimeScope.cs index c4fb8bd5..f321625b 100644 --- a/VContainer/Assets/VContainer/Runtime/Unity/LifetimeScope.cs +++ b/VContainer/Assets/VContainer/Runtime/Unity/LifetimeScope.cs @@ -263,6 +263,8 @@ public TScope CreateChildFromPrefab(TScope prefab, IInstaller installer where TScope : LifetimeScope { var wasActive = prefab.gameObject.activeSelf; + using var dirtyScope = new ObjectResolverUnityExtensions.PrefabDirtyScope(prefab.gameObject); + if (wasActive) { prefab.gameObject.SetActive(false); diff --git a/VContainer/Assets/VContainer/Runtime/Unity/ObjectResolverUnityExtensions.cs b/VContainer/Assets/VContainer/Runtime/Unity/ObjectResolverUnityExtensions.cs index 15af3d90..5ec4adf6 100644 --- a/VContainer/Assets/VContainer/Runtime/Unity/ObjectResolverUnityExtensions.cs +++ b/VContainer/Assets/VContainer/Runtime/Unity/ObjectResolverUnityExtensions.cs @@ -1,3 +1,4 @@ +using System; using UnityEngine; using VContainer.Internal; @@ -5,6 +6,31 @@ namespace VContainer.Unity { public static class ObjectResolverUnityExtensions { + public readonly struct PrefabDirtyScope : IDisposable + { + private readonly GameObject _prefab; + private readonly bool _madeDirty; + + public PrefabDirtyScope(GameObject prefab) + { + _prefab = prefab; + +#if UNITY_EDITOR + _madeDirty = prefab.activeSelf && !UnityEditor.EditorUtility.IsDirty(_prefab); +#endif + } + + public void Dispose() + { +#if UNITY_EDITOR + if (_madeDirty) + { + UnityEditor.EditorUtility.ClearDirty(_prefab); + } +#endif + } + } + public static void InjectGameObject(this IObjectResolver resolver, GameObject gameObject) { void InjectGameObjectRecursive(GameObject current) @@ -45,6 +71,8 @@ public static T Instantiate(this IObjectResolver resolver, T prefab, Transfor where T : Component { var wasActive = prefab.gameObject.activeSelf; + using var dirtyScope = new PrefabDirtyScope(prefab.gameObject); + prefab.gameObject.SetActive(false); var instance = UnityEngine.Object.Instantiate(prefab, parent, worldPositionStays); @@ -88,6 +116,8 @@ public static T Instantiate( where T : Component { var wasActive = prefab.gameObject.activeSelf; + using var dirtyScope = new PrefabDirtyScope(prefab.gameObject); + prefab.gameObject.SetActive(false); var instance = UnityEngine.Object.Instantiate(prefab, position, rotation, parent); @@ -111,6 +141,8 @@ static T Instantiate(this LifetimeScope scope, T prefab, Vector3 position, Qu where T : Component { var wasActive = prefab.gameObject.activeSelf; + using var dirtyScope = new PrefabDirtyScope(prefab.gameObject); + prefab.gameObject.SetActive(false); T instance; @@ -144,6 +176,8 @@ static T Instantiate(this LifetimeScope scope, T prefab, Vector3 position, Qu static GameObject Instantiate(this LifetimeScope scope, GameObject prefab, Vector3 position, Quaternion rotation) { var wasActive = prefab.activeSelf; + using var dirtyScope = new PrefabDirtyScope(prefab.gameObject); + prefab.SetActive(false); GameObject instance; @@ -182,6 +216,8 @@ public static GameObject Instantiate(this IObjectResolver resolver, GameObject p public static GameObject Instantiate(this IObjectResolver resolver, GameObject prefab, Transform parent, bool worldPositionStays = false) { var wasActive = prefab.activeSelf; + using var dirtyScope = new PrefabDirtyScope(prefab.gameObject); + prefab.SetActive(false); GameObject instance = null; @@ -221,6 +257,8 @@ public static GameObject Instantiate( Transform parent) { var wasActive = prefab.activeSelf; + using var dirtyScope = new PrefabDirtyScope(prefab.gameObject); + prefab.SetActive(false); var instance = UnityEngine.Object.Instantiate(prefab, position, rotation, parent); From f0731a1f2b8423f744df8fb59d1ac187497a23f0 Mon Sep 17 00:00:00 2001 From: yellowisher Date: Sat, 9 Nov 2024 23:01:24 +0900 Subject: [PATCH 2/3] Remove unnecessary .gameObject access --- .../Runtime/Unity/ObjectResolverUnityExtensions.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/VContainer/Assets/VContainer/Runtime/Unity/ObjectResolverUnityExtensions.cs b/VContainer/Assets/VContainer/Runtime/Unity/ObjectResolverUnityExtensions.cs index 5ec4adf6..29e5a3db 100644 --- a/VContainer/Assets/VContainer/Runtime/Unity/ObjectResolverUnityExtensions.cs +++ b/VContainer/Assets/VContainer/Runtime/Unity/ObjectResolverUnityExtensions.cs @@ -176,7 +176,7 @@ static T Instantiate(this LifetimeScope scope, T prefab, Vector3 position, Qu static GameObject Instantiate(this LifetimeScope scope, GameObject prefab, Vector3 position, Quaternion rotation) { var wasActive = prefab.activeSelf; - using var dirtyScope = new PrefabDirtyScope(prefab.gameObject); + using var dirtyScope = new PrefabDirtyScope(prefab); prefab.SetActive(false); @@ -216,7 +216,7 @@ public static GameObject Instantiate(this IObjectResolver resolver, GameObject p public static GameObject Instantiate(this IObjectResolver resolver, GameObject prefab, Transform parent, bool worldPositionStays = false) { var wasActive = prefab.activeSelf; - using var dirtyScope = new PrefabDirtyScope(prefab.gameObject); + using var dirtyScope = new PrefabDirtyScope(prefab); prefab.SetActive(false); @@ -257,7 +257,7 @@ public static GameObject Instantiate( Transform parent) { var wasActive = prefab.activeSelf; - using var dirtyScope = new PrefabDirtyScope(prefab.gameObject); + using var dirtyScope = new PrefabDirtyScope(prefab); prefab.SetActive(false); From 0f8a97739c0d177e6d893da4af601e4fa1e94eb6 Mon Sep 17 00:00:00 2001 From: yellowisher Date: Tue, 12 Nov 2024 01:26:23 +0900 Subject: [PATCH 3/3] Add #UNITY_2020_1_OR_NEWER wrapping to EditorUtility functions --- .../VContainer/Runtime/Unity/ObjectResolverUnityExtensions.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/VContainer/Assets/VContainer/Runtime/Unity/ObjectResolverUnityExtensions.cs b/VContainer/Assets/VContainer/Runtime/Unity/ObjectResolverUnityExtensions.cs index 29e5a3db..337a6bb4 100644 --- a/VContainer/Assets/VContainer/Runtime/Unity/ObjectResolverUnityExtensions.cs +++ b/VContainer/Assets/VContainer/Runtime/Unity/ObjectResolverUnityExtensions.cs @@ -15,14 +15,14 @@ public PrefabDirtyScope(GameObject prefab) { _prefab = prefab; -#if UNITY_EDITOR +#if UNITY_EDITOR && UNITY_2020_1_OR_NEWER _madeDirty = prefab.activeSelf && !UnityEditor.EditorUtility.IsDirty(_prefab); #endif } public void Dispose() { -#if UNITY_EDITOR +#if UNITY_EDITOR && UNITY_2020_1_OR_NEWER if (_madeDirty) { UnityEditor.EditorUtility.ClearDirty(_prefab);