Tasharen Entertainment Forum

Support => NGUI 3 Support => Topic started by: Rafe on August 19, 2012, 08:20:53 PM

Title: DestroyImmediate Bug
Post by: Rafe on August 19, 2012, 08:20:53 PM
Hi,

Some of your code is allowing destroy immediate with a test: Application.isEditor

I think what you want here is !Application.isPlaying instead.

I'm getting some errors because from this. Specifically:
UIPanel OnDisable line 552:
  1.                         if (dc != null) NGUITools.DestroyImmediate(dc.gameObject);
  2.  

What I find confusing is that the NGUITools.Destroy() is already doing a destroy immedate when the game is not running, so I updated this line to call that method instead.
  1.             if (dc != null) NGUITools.Destroy(dc.gameObject);
  2.  

So far this change seems stable.

- Rafe
Title: Re: DestroyImmediate Bug
Post by: ArenMook on August 19, 2012, 10:53:24 PM
No, that part must remain as it is. Try turning on geometry debugging on your panel. You will notice that now your draw call objects are no longer being destroyed properly when you go from play to edit mode.
Title: Re: DestroyImmediate Bug
Post by: Rafe on August 20, 2012, 01:30:22 AM
I see that now. When I load the level it is fine, but if I start the game with that scene it is a problem.

So, how can I stop the error? Granted it should only occur in the Editor, but there must be a way to run error free. Any idea what this error may cause?

Does it have anything to do with SetActiveRecursively?

  1. Destroying object immediately is not permitted during physics trigger and contact callbacks. You must use Destroy instead.
  2. UnityEngine.Object:DestroyImmediate(Object)
  3. NGUITools:DestroyImmediate(Object) (at Assets/NGUI/Scripts/Internal/NGUITools.cs:449)
  4. UIPanel:OnDisable() (at Assets/NGUI/Scripts/UI/UIPanel.cs:552)
  5. UnityEngine.GameObject:SetActiveRecursively(Boolean)   //  <--- Run by another plugin
  6. [...snip...]
  7.  
Title: Re: DestroyImmediate Bug
Post by: ArenMook on August 20, 2012, 01:49:42 PM
What other plugin would it be? You can't completely deactivate all widgets of a panel during a physics callback. I suggest delaying that. Set some flag that will be checked in update, and if true, do your SetActive stuff.
Title: Re: DestroyImmediate Bug
Post by: Rafe on August 20, 2012, 11:06:33 PM
Any idea how to tell? It is a pretty common event. Something enters a collider trigger and it triggers deactivation. This is the first time I have encountered a need to destroy-immediate during game play.
Title: Re: DestroyImmediate Bug
Post by: ArenMook on August 21, 2012, 12:32:17 AM
Tell what? What causes it? Just follow the stack trace. As I mentioned, just delay the deactivation until it's outside the physics callback. For example, if you're doing something inside OnTriggerEnter that causes your UI to hide, just set a boolean flag "hideNow" to 'true', and pick it up in that script's Update.
Title: Re: DestroyImmediate Bug
Post by: Rafe on August 21, 2012, 12:45:41 AM
I don't use Update() unless it is a very low frequency implementation. For example, using it on every enemy in our game would kill performance. Everything is done with direct calls or delegates and co-routines. In this particular case imagine a bullet hitting an enemy. The enemy is told it is hit directly when the bullet's collider makes contact. In this OnHit() function, the enemy decides it is dead and "despawns" (pooled) via deactivation (and just before it does, it also despawns its life-bar). I am pretty sure there is no way to delay this until later in the current frame since this is async and you can't really be sure if you can trigger something before the end of the frame. Update() already ran anyway. To do what you suggest, I think i would have to wait for the next frame? The trouble with this is it is a pretty major game-play workaround for a single UI issue. The GUI layer shouldn't need to dictate what the game needs to do.

Doesn't Destroy() already queue destruction for later for this exact reason? Why is destroy-immediate needed during game-play?

The docs say:
Quote
Destroys the object obj immediately. It is strongly recommended to use Destroy instead.

This function should only be used when writing editor code since the delayed destruction will never be invoked in edit mode. In game code it is recommended to use Object.Destroy instead. Destroy is always delayed (but executed within the same frame...

Maybe I'm just tired, but I can't think of a reason this can't work with regular Destroy().
Title: Re: DestroyImmediate Bug
Post by: ArenMook on August 21, 2012, 01:04:35 PM
DestroyImmediate is needed for it to work when going from Play to Edit mode. If you use Destroy here, it doesn't actually get destroyed.

You can always use a StartCoroutine in your physics callback to create a temporary update function. Inside it do your disabling.
Title: Re: DestroyImmediate Bug
Post by: winresh24 on October 01, 2012, 08:45:53 AM
I dont know what is wrong here plss help me........

static public void DestroyImmediate (UnityEngine.Object obj)
   {
      if (obj != null)
      {
         if (Application.isEditor) UnityEngine.Object.Destroy(obj);
         else UnityEngine.Object.Destroy(obj);
      }
   }

error!!!!!

Destroy may not be called from edit mode! Use DestroyImmediate instead.
Also think twice if you really want to destroy something in edit mode. Since this will destroy objects permanently.
UnityEngine.Object:Destroy(Object)
NGUITools:DestroyImmediate(Object) (at Assets/Plugins/Internal/NGUITools.cs:459)
UIPanel:OnDisable() (at Assets/Plugins/UI/UIPanel.cs:524)
Title: Re: DestroyImmediate Bug
Post by: ArenMook on October 01, 2012, 04:48:47 PM
What version of NGUI are you using? Our line numbers don't match.
Title: Re: DestroyImmediate Bug
Post by: Bovine on January 28, 2013, 02:36:19 PM
I have the same issue. I see you're saying the editor needs DestroyImmediate() or for some reason it leaves something hanging around, is that right?

And the DestroyImmediate() has to happen there and then, presumably that cannot be farmed off into a Coroutine?

I'm a little uneasy about having to start coroutines to destroy stuff in game for the sake of working around editor behaviour - is there really no other way around this?
Title: Re: DestroyImmediate Bug
Post by: ArenMook on January 28, 2013, 02:44:30 PM
None.
Title: Re: DestroyImmediate Bug
Post by: imtrobin on July 09, 2014, 12:23:37 PM
I'm surprised I have to do this workaround. Daikon Forge can do it without needing this kind of hack. I don't know NGUI architecture well enough but can't it do a delayed destruction internally instead using OnDestroy and check Application is quitting like so

http://forum.unity3d.com/threads/possible-to-bypass-ondisable-on-application-quit.29594/