Author Topic: DestroyImmediate Bug  (Read 11302 times)

Rafe

  • Jr. Member
  • **
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 78
    • View Profile
DestroyImmediate Bug
« 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

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: DestroyImmediate Bug
« Reply #1 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.

Rafe

  • Jr. Member
  • **
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 78
    • View Profile
Re: DestroyImmediate Bug
« Reply #2 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.  

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: DestroyImmediate Bug
« Reply #3 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.

Rafe

  • Jr. Member
  • **
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 78
    • View Profile
Re: DestroyImmediate Bug
« Reply #4 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.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: DestroyImmediate Bug
« Reply #5 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.

Rafe

  • Jr. Member
  • **
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 78
    • View Profile
Re: DestroyImmediate Bug
« Reply #6 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().

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: DestroyImmediate Bug
« Reply #7 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.

winresh24

  • Guest
Re: DestroyImmediate Bug
« Reply #8 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)

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: DestroyImmediate Bug
« Reply #9 on: October 01, 2012, 04:48:47 PM »
What version of NGUI are you using? Our line numbers don't match.

Bovine

  • Guest
Re: DestroyImmediate Bug
« Reply #10 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?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: DestroyImmediate Bug
« Reply #11 on: January 28, 2013, 02:44:30 PM »
None.

imtrobin

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 2
    • View Profile
Re: DestroyImmediate Bug
« Reply #12 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/