Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
2
Question by psyfreak · Feb 18, 2011 at 07:48 PM · componentremoveeditdestroyimmediate

Editor DestroyImmediate Remove component via script

My issue: I would like to add a component dynamically at Design/Editor Time if a checkbox is on and remove it if checkbox is off.

My code: Component1 uses [CustomEditor(typeof(Component1))] and Component2 uses [CustomEditor(typeof(Component2))]

ObjSceneComp is target of Component1 Inspector GUI.

if(CheckboxComponent1) { //if no Component2 added if(Component2Exists== false) { ObjSceneComp.gameObject.AddComponent<Component2>();

         }
     }
     else {
         if(Component2Exists== true) {
             DestroyImmediate( ObjSceneComp.gameObject.GetComponent&lt;Component2&gt;());  
         }
     }

}

It all works fine, but I always get this error: MissingReferenceException: The object of type 'EKISharedDataComponent' has been destroyed but you are still trying to access it. Your script should either check if it is null or you should not destroy the object.

If I take instead of Component2 an normal script without a CustomEditor behind Unity is going to crash.

Comment
Add comment · Show 3
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Bunny83 · Feb 18, 2011 at 09:27 PM 0
Share

You just posted some snippets of your code, but i can't deter$$anonymous$$e what it is supposed to do. What is ChechboxComponent1 and where is it set? What is Component2Exists and where is it set? Is "test" relevant for your problem? $$anonymous$$aybe edit your question and add relevant code and remove irrelevant parts.

avatar image psyfreak · Feb 19, 2011 at 01:12 AM 0
Share

ChechboxComponent1 is set within the CustomEditor-GUI for component1. Sorry my mistake: test is Component2Exists please substitute test through Component2Exists. within the start test is always false.

avatar image psyfreak · Feb 19, 2011 at 01:14 AM 0
Share

didnt saw the edit - changed.

4 Replies

· Add your reply
  • Sort: 
avatar image
26

Answer by margutteter · Apr 24, 2015 at 03:51 AM

I found another solution for this... If a custom inspector removes a component on the same game object, during the same iteration of drawing the inspector, Unity will encounter the removed component and error trying to draw it.

Using EditorGUIUtility.ExitGUI() will stop the execution of the current draw iteration, starting over from the top, at which point the removed component will not be attempted to be drawn.

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image ifdef_ben · Nov 24, 2016 at 09:32 PM 0
Share

It's also good to note that calling EditorGUIUtility.ExitGUI() in the scope of OnInspectorGUI() will also interrupt the execution of the Inspector of the current component (having the same effect as "return;"), not just the next components. So you should only call this after all the code you need in the current inspector has been executed.

avatar image Bunny83 ifdef_ben · Nov 25, 2016 at 10:33 AM 0
Share

That's pretty irrelevant for several reasons.

First of all the current execution of the inspector is an input event and not a repaint event so there will be no visual difference. It has to be an input event (like "mouseup" ) since you most likely removed the component in reaction to a button click or key press.

Next thing is since some component has handled that input event (for example a Button has called "Use()" on that event), the event type is set to "Ignore" for everything that follows, no matter if it's in your inspector or in any other. So the event has no use for anything else. It just causes problems hence the ExitGUI

Finally when you call ExitGUI you actually raise an exception that is silently caught by Unity. Unity will immediately repaint the whole inspector anyways. So it doesn't matter if you call ExitGUI adter some other things or not ^^.

ExitGUI is also used by some internal controls. You need it when you somehow start a new GUI call due to some actions. A common case are native popup windows or opening EditorWindows from inside the inspector. One example i can think of is the ColorField. When you click on it, it opens the color picker window. After opening the window it immediately called ExitGUI to prevent the corruption of the layout stack which has been altered by the just opened window.

This is the snipped which is executed when you click with the left mouse button onto the ColorField:

 {
     GUIUtility.keyboardControl = id;
     EditorGUI.show$$anonymous$$ixedValue = false;
     ColorPicker.Show(GUIView.current, value, showAlpha, hdr, hdrConfig);
     GUIUtility.ExitGUI();
 }

avatar image ifdef_ben Bunny83 · Nov 25, 2016 at 04:42 PM 1
Share

I don't see why this is irrelevant in any way. The fact that ExitGUI() is raising a silent exception is especially the reason why it's important to make sure that all the code you need is called before calling ExitGUI(). Your example does not di$$anonymous$$ish my point in any way, all the relevant execution is done before ExitGUI().

$$anonymous$$aybe you'll understand why this is valuable information with an example. Let's say I want to replace one component with another, doing this won't work:

     public override void OnInspectorGUI()
     {        
             if(GUILayout.Button("Change components")){
                     ClearFooComponents();
                     AddBarComponents();
             }
     }
     
     private void ClearFooComponents()
     {
             Component selectedComponent = target as Component;
             Component[] fooComponents = selectedComponent.GetComponents<Foo>();
             foreach (Component currentComponent in fooComponents)
             {
                     DestroyImmediate(currentComponent);
             }
             EditorGUIUtility.ExitGUI();
     }

As ExitGUI() is called in the ClearFooComponents() function, AddBarComponents() will never be executed. $$anonymous$$nowing that calling ExitGUI() interupts the flow of execution is relevant information. For the code to work you would have to call ExitGUI() after AddBarComponents().

avatar image bulathard · Jun 17, 2017 at 11:46 AM 0
Share

Thank you very much!))

avatar image
2

Answer by psyfreak · Mar 19, 2011 at 01:21 PM

I solved it myself:

You have to hide it it via a flag from your script. That flag you have to use for (un-)hiding in OnInspector function. If the component is hidden, then you can do the the DestroyImmediate as far as you have no scripts or other comps, which access your current component.

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image joonturbo · Sep 23, 2014 at 12:06 PM 0
Share

could you post the code for this?

avatar image Julien-Lynge · Mar 15, 2015 at 09:43 PM 0
Share

Not sure if something has changed in Unity 5, but just setting the hide flags doesn't seem to work.

Here's the super-hacky way I solved it:

  • Within your custom editor script, save the component you want to destroy to a private static variable

  • Set the hide flags (I just used (HideFlags)int.$$anonymous$$axValue)

  • Then, at the top of your OnInspectorGUI function, add a check to delete the component if it's not null. That will force a deletion the following frame, and you won't see the exception.

avatar image
0

Answer by steven3Dim · Jun 22, 2017 at 08:51 AM

The problem is that the component is still visible in the inspector. Instead of calling

 DestroyImmediate(CharacterDecal);

Use:

 CharacterDecal.hideFlags |= HideFlags.HideInInspector;
 DestroyImmediate(CharacterDecal);

This worked for me on Unity 5.5.3f1

Edit: Oh this doesn't work: seems I tested it in play-mode.

If you can live with not having the component in the editor, you could set

 CharacterDecal.hideFlags |= HideFlags.HideInInspector;

immediately when you created the component. The problem arises, because in the same frame the inspector is draw, it still holds a reference. So your component should be hidden already in the frame before you destroy it, or there should be a way to correctly notify the inspector, which I found not. Some users say to use UnityEngine.GUIUtility.ExitGUI () which throws an exception, but it is an internal function only and only has effect when in the GUI drawing routine I suspect.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by That1phillps · Oct 21, 2019 at 09:32 PM

But before all of these things, first try restarting your computer. I did that, and it worked...

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

6 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

(Editor) How to delete duplicate components from GameObject that persists when the scene reloads 0 Answers

Component Find and Replace: execute's fine, fails to do anything?! 1 Answer

Get GameObject from List based on attached script or assigned name 3 Answers

2D Animation does not start 1 Answer

GameObject permanent destruction from "Resources" in EditorWindow 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges