SmartReplace icon indicating copy to clipboard operation
SmartReplace copied to clipboard

Compatibility for unity 2020.3?

Open nehvaleem opened this issue 4 years ago • 7 comments

@Moolt - I've just stumbled upon this tool and it would be a lifesaver for me, but sadly it isn't compatible with Unity 2020.3 (the External References part is causing the problems). Is it possible to update this wonderful plugin in any way?

nehvaleem avatar Oct 20 '21 15:10 nehvaleem

@nehvaleem I've just updated the package to Unity 2020.3. It works fine in the example scene so I hope your issue is also resolved. If not, I need some more details.

Moolt avatar Oct 20 '21 16:10 Moolt

Awesome, much appreciated! I'll check it right away. Previously I've had issues with the external references throwing an exception. Also - does your plugin handles timelines and their bindings when external references are being checked?

nehvaleem avatar Oct 21 '21 07:10 nehvaleem

Yeah, my issue is still there. I am trying to replace rather complex object, but the scene & fresh prefab all shares one common original prefab. I am just trying to replace one prefab variant with a different one.

I am getting an InvalidCastException like this:

InvalidCastException: Specified cast is not valid.
(wrapper castclass) System.Object.__castclass_with_cache(object,intptr,intptr)
SmartReplace.Scripts.Editor.ReplacePrefabsWindow.GetValueAsListFor[T] (UnityEngine.Component source, System.Reflection.FieldInfo field, System.Boolean isList) (at Assets/SmartReplace/Scripts/Editor/ReplacePrefabsWindow.cs:639)
SmartReplace.Scripts.Editor.ReplacePrefabsWindow.FindReferencesOn[T] (SmartReplace.Scripts.Editor.FindReferenceBaseParameter param, System.Collections.Generic.Dictionary`2[TKey,TValue] hierarchyMapping, SmartReplace.Scripts.Editor.ReplacePrefabsWindow+GetHierarchyFor`1[T] getHierarchyFor) (at Assets/SmartReplace/Scripts/Editor/ReplacePrefabsWindow.cs:571)
SmartReplace.Scripts.Editor.ReplacePrefabsWindow.FindExternalReferences () (at Assets/SmartReplace/Scripts/Editor/ReplacePrefabsWindow.cs:533)
SmartReplace.Scripts.Editor.ReplacePrefabsWindow.ReplaceAll () (at Assets/SmartReplace/Scripts/Editor/ReplacePrefabsWindow.cs:323)
SmartReplace.Scripts.Editor.ReplacePrefabsWindow.OnGUI () (at Assets/SmartReplace/Scripts/Editor/ReplacePrefabsWindow.cs:212)
UnityEditor.HostView.InvokeOnGUI (UnityEngine.Rect onGUIPosition, UnityEngine.Rect viewRect) (at <5ad584e208e14caaa9e6b2e6027e9204>:0)
UnityEditor.DockArea.DrawView (UnityEngine.Rect viewRect, UnityEngine.Rect dockAreaRect) (at <5ad584e208e14caaa9e6b2e6027e9204>:0)
UnityEditor.DockArea.OldOnGUI () (at <5ad584e208e14caaa9e6b2e6027e9204>:0)
UnityEngine.UIElements.IMGUIContainer.DoOnGUI (UnityEngine.Event evt, UnityEngine.Matrix4x4 parentTransform, UnityEngine.Rect clippingRect, System.Boolean isComputingLayout, UnityEngine.Rect layoutSize, System.Action onGUIHandler, System.Boolean canAffectFocus) (at <08270fb28ecf479b927dcf4fe817bc07>:0)
UnityEngine.UIElements.IMGUIContainer.HandleIMGUIEvent (UnityEngine.Event e, UnityEngine.Matrix4x4 worldTransform, UnityEngine.Rect clippingRect, System.Action onGUIHandler, System.Boolean canAffectFocus) (at <08270fb28ecf479b927dcf4fe817bc07>:0)
UnityEngine.UIElements.IMGUIContainer.HandleIMGUIEvent (UnityEngine.Event e, System.Action onGUIHandler, System.Boolean canAffectFocus) (at <08270fb28ecf479b927dcf4fe817bc07>:0)
UnityEngine.UIElements.IMGUIContainer.HandleIMGUIEvent (UnityEngine.Event e, System.Boolean canAffectFocus) (at <08270fb28ecf479b927dcf4fe817bc07>:0)
UnityEngine.UIElements.IMGUIContainer.SendEventToIMGUIRaw (UnityEngine.UIElements.EventBase evt, System.Boolean canAffectFocus, System.Boolean verifyBounds) (at <08270fb28ecf479b927dcf4fe817bc07>:0)
UnityEngine.UIElements.IMGUIContainer.SendEventToIMGUI (UnityEngine.UIElements.EventBase evt, System.Boolean canAffectFocus, System.Boolean verifyBounds) (at <08270fb28ecf479b927dcf4fe817bc07>:0)
UnityEngine.UIElements.IMGUIContainer.HandleEvent (UnityEngine.UIElements.EventBase evt) (at <08270fb28ecf479b927dcf4fe817bc07>:0)
UnityEngine.UIElements.CallbackEventHandler.HandleEventAtTargetPhase (UnityEngine.UIElements.EventBase evt) (at <08270fb28ecf479b927dcf4fe817bc07>:0)
UnityEngine.UIElements.MouseCaptureDispatchingStrategy.DispatchEvent (UnityEngine.UIElements.EventBase evt, UnityEngine.UIElements.IPanel panel) (at <08270fb28ecf479b927dcf4fe817bc07>:0)
UnityEngine.UIElements.EventDispatcher.ApplyDispatchingStrategies (UnityEngine.UIElements.EventBase evt, UnityEngine.UIElements.IPanel panel, System.Boolean imguiEventIsInitiallyUsed) (at <08270fb28ecf479b927dcf4fe817bc07>:0)
UnityEngine.UIElements.EventDispatcher.ProcessEvent (UnityEngine.UIElements.EventBase evt, UnityEngine.UIElements.IPanel panel) (at <08270fb28ecf479b927dcf4fe817bc07>:0)
UnityEngine.UIElements.EventDispatcher.ProcessEventQueue () (at <08270fb28ecf479b927dcf4fe817bc07>:0)
UnityEngine.UIElements.EventDispatcher.OpenGate () (at <08270fb28ecf479b927dcf4fe817bc07>:0)
UnityEngine.UIElements.EventDispatcherGate.Dispose () (at <08270fb28ecf479b927dcf4fe817bc07>:0)
UnityEngine.UIElements.EventDispatcher.ProcessEvent (UnityEngine.UIElements.EventBase evt, UnityEngine.UIElements.IPanel panel) (at <08270fb28ecf479b927dcf4fe817bc07>:0)
UnityEngine.UIElements.EventDispatcher.Dispatch (UnityEngine.UIElements.EventBase evt, UnityEngine.UIElements.IPanel panel, UnityEngine.UIElements.DispatchMode dispatchMode) (at <08270fb28ecf479b927dcf4fe817bc07>:0)
UnityEngine.UIElements.BaseVisualElementPanel.SendEvent (UnityEngine.UIElements.EventBase e, UnityEngine.UIElements.DispatchMode dispatchMode) (at <08270fb28ecf479b927dcf4fe817bc07>:0)
UnityEngine.UIElements.UIElementsUtility.DoDispatch (UnityEngine.UIElements.BaseVisualElementPanel panel) (at <08270fb28ecf479b927dcf4fe817bc07>:0)
UnityEngine.UIElements.UIElementsUtility.UnityEngine.UIElements.IUIElementsUtility.ProcessEvent (System.Int32 instanceID, System.IntPtr nativeEventPtr, System.Boolean& eventHandled) (at <08270fb28ecf479b927dcf4fe817bc07>:0)
UnityEngine.UIElements.UIEventRegistration.ProcessEvent (System.Int32 instanceID, System.IntPtr nativeEventPtr) (at <08270fb28ecf479b927dcf4fe817bc07>:0)
UnityEngine.UIElements.UIEventRegistration+<>c.<.cctor>b__1_2 (System.Int32 i, System.IntPtr ptr) (at <08270fb28ecf479b927dcf4fe817bc07>:0)
UnityEngine.GUIUtility.ProcessEvent (System.Int32 instanceID, System.IntPtr nativeEventPtr, System.Boolean& result) (at <00a477ed1abf4030be646c3244bd3667>:0)

I think it is related to the Transfer External References which I need the most. I'll try to narrow it down or maybe prepare some repro, but it would be awesome if you could take a look by yourself.

nehvaleem avatar Oct 21 '21 08:10 nehvaleem

I have narrowed it down to one project-specific component of mine, but for now, I am unable to isolate it, but I can work around it.

On the other hand, I have found out that this plugin:

  1. Does not handle playable bindings at all.
  2. Does not handle lists with serializable classes that hold a reference to the replaced objects. Imagine a List<CustomType> and CustomType has a field for the component or GameObject that we are trying to replace.
  3. Does not handle inactive GameObjects that are holding a reference to replaced object

Do you even consider extending SmartReplace to support such cases? I probably don't have to say it, but it would be totally awesome if you do:)

nehvaleem avatar Oct 21 '21 09:10 nehvaleem

I don't know much about timelines or playable bindings. But as stated in the Readme, default Unity Components are not supported. The plugin was initially written three years ago when nested prefabs didn't exist, so I wouldn't be surprised if that's also causing problems.

Some of your cases may be very hard / impossible for me to handle. But if you provide a project where I can reproduce these issues I could try. It's hard to fix bugs like this from just a stacktrace.

Moolt avatar Oct 21 '21 10:10 Moolt

Don't worry. My main issue was caused by a prefab structure. Some nested GameObject had a Component that referenced another one on the root. That made the FindExternalReferences method to fail.

I have fixed it by adding a check like this:

var allComponentsInScene = allObjectsInScene
                .SelectMany(s => GameObjectHelper.GetComponentsSafe<Component>(s).Where(c => !c.transform.IsChildOf(brokenPrefab.transform) ))
                .Where(c => c.GetType().Namespace != "UnityEngine").ToList();

In terms of playable and more sophisticated things. Don't bother, I have extended your plugin to support some custom post processors for replace process and I am managing those references by myself since they are pretty custom ones.

nehvaleem avatar Oct 21 '21 13:10 nehvaleem

Glad you could resolve the issue. I would appreciate a pull request with your changes .😊

Moolt avatar Oct 21 '21 13:10 Moolt