I can’t seem to find anything in Unity script reference which refers to something like this. It seems a perfectly reasonable feature to add to the engine.
I Have a menu system where I have buttons which take in a menu to activate/deactivate, which all works fine. The problem is, I want to make sure a certain function is called before one of the gameobjects is deactivated.
Now I could do this using reflection and searching the method generically by type in my button script, but that seems overkill. Is there a hidden event that is not on the scripting reference to tell me when a go active state changes?
I have also thought about writing a custom static function which I can call which will setActive an gameobject and allow me to do anything I want, but since I can’t modify the unity core code and alot of my scripts are not connected to each other, this also seems like a lot of extra work for a simple thing.
There is also the possibility I am missing something extremely simple, any help is greatly appreciated!
I assume your using the SetActive() function to activate/deactivate your gameobject… why can’t you just call your function before that one? If you need a delay make a timer.
Hey, thanks for the reply, the problem is, I am trying to keep my button object as clean as possible, and forcing it to rely on every object using it to contain a specific function is less than ideal. I need a way which keeps the entire thing generic, If that makes sense.
Well once you call the SetActive() function it’s going to do just that… there isn’t a way that I know of that can be like “Oh he wants to set the objects active state to false? lets let him know we are going to do this and wait for a confirmation before we do” lol that would just be silly. It’s up to you to specify what you want to do before you change the active state of an object. If you want it to be cleaner you could write a new function that will call your function and delay your SetActive() and then just call that function instead… if that makes sense lol
Well in this case it’s different, this would tell you when a script is disabled… and if you want something like that to check for a game object to be disabled you would just handle it with… if(gameObject.activeSelf == false)
You’re right, but in my case this was the perfect solution as when I change menus, I deactivate the parent object which in turn disables all other gameobjects(and inherently their components) . If my entire gameObject hierarchy was deactivated, any component within would not be able to check if(gameObject.activeSelf) as you know.
So ye, just thought I should explain why it was a good solution for me! Thanks.
I completely agree that some kind of generic event system that we can hook into for a wider variety of events would be excellent. However, in this case, I think that an ample solution would be to stick a listener component on the GameObject in question that does what you desire in OnDisable().
Edit: Haha, I should have read the next few posts… silly!
Sorry for the revival of a very old post, but I was looking just this thing and came to this post, which it didn’t help me at first, but got me in the right direction. Now I have the correct answer and thought to post it for archive’s sake and to help any future wanderer.
To capture the Enabled/Disabled events of a GameObject you simply have to use OnDisable() and OnEnable() which they come with MonoBehaviour by default.
It isn’t, actually, or at least no more than the previous answers. OnDisable() and OnEnable() are MonoBehaviour functions, not GameObject functions. That means that they check if the script/component is enabled or disabled, and not the GameObject itself. This could lead to false-positives when the script gets disabled and you treat it as if the whole object is.
The correct answer was posted several years ago (several posts up) here. The answer is to use the OnDisable() and OnEnable() functions of the component in order to check the status of the GameObject, and then react if the entire thing has been disabled. Next time you should read to the end of the thread first IMO.
This worked for me. Thanks for the post! (I use OnEnable() to instead of a start function for windows that get SetActive(false) and true and have scripts attached to them.)
OnEnable() and OnDisable() are the right answer. It’s generally better practice to not mutate the API if you don’t have to, especially when you want your component to play nicely with a well established ecosystem and all the knowledge and expectations on top of it. Adding your own “setActive” method and then educating everyone about its purpose and how to use it, coding protection against misuse, it’s not going to fly well.
Anyway – Post #12 was helpful for me. Good idea considering the state of the gameObject owning the Component
My solution for that was not disable the game object but just make it invisible and do not receive the touch event anymore, my script below overrides both 3D objects and sprites, that way the object still having my event listeners and can appear and react accordingly.
Use this to extend GameObject:
// Do not use gameObject.SetActive(bool) because OnDisable() will stop the listeners
public static void _SetVisibility(this GameObject gameObject, bool visible)
{
/*
For 3D Objects
*/
Renderer renderer = gameObject.GetComponent();
if (renderer != null)
{
renderer.enabled = visible;
}
Renderer[ ] renderers = gameObject.GetComponentsInChildren();
if (renderers != null)
{
foreach (var r in renderers)
{
r.enabled = visible;
}
}
Collider collider = gameObject.GetComponent();
if (collider != null)
{
collider.enabled = visible;
}
Renderer[ ] colliders = gameObject.GetComponentsInChildren();
if (colliders != null)
{
foreach (var c in colliders)
{
c.enabled = visible;
}
}
/*
For UI Sprites Object
*/
Image image = gameObject.GetComponent();
if (image != null)
{
image.enabled = visible;
}
}
Thanks @feds that worked for my situation. I was doing that sort of thing for my player gameobject (when dead and should be invisible), but that extension works great, like when using CullingGroup on objects that will be disabled and reenabled.
I’m having a similar problem but none of the suggested solutions work: when a GameObject is deactivated by an external script, I need any scripts attached to that GameObject to run “shut down” code before the script is deactivated, but OnDisable() doesn’t work for some reason (either because it isn’t run if the GameObject (but not the script) is deactivated, or because the GO is being deactivated by another, external script). Anyone know why OnDisable() isn’t called in this case or what type of workaround is available?