Search Unity

Add event listeners without OnEnable/Awake?

Discussion in 'Scripting' started by Shack_Man, Jan 25, 2021.

  1. Shack_Man

    Shack_Man

    Joined:
    Jun 7, 2017
    Posts:
    372
    I have a game character that when getting clicked on, a bunch of panels open up. I achieve this by having the character call a static event upon clicking it. That way it works for all instances of that character and I can easily add or remove objects that react to it without having to modify the character.

    The problem is that those panels still need to subscribe to it. I have 2 ways I use and neither one is awesome:

    1. Make the panels active in the scene so OnEnable gets called, where the listener is added, then disable them in the same frame. Very impractical as I need all those panels to be active on build/testing.

    2. Have a class that does the subscribing. E.g. a serialized field for every panel, in Awake it subscribes the classes to the right events. Ok but not as dynamic.

    Is there a much better way to do that?
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,748
    OnEnable/OnDisable is really the most-popular pattern in Unity for this and it is rock-solid reliable. You can even combine it with a singleton pattern so that your resources fires itself up automagically and only once.

    Unfortunately you can't use static constructors for stuff like this because Unity isn't ready for business when those are created, and everything in scripting must be done in Unity's main thread.

    Unity does not really "run" code the way you'd expect with your own engine or other run contexts.

    All Unity does is "load the first scene," and after that it's up to you to put scripts in that scene that take you through all the rest of your game.
     
    Shack_Man likes this.
  3. Reahreic

    Reahreic

    Joined:
    Mar 23, 2011
    Posts:
    254
    The way I handle this type of requirement is to have a separate scene for UI components, world & screen space. All UI elements are linked to or instantiate, and controlled by a singleton UIManager class which handles referencing. Said UI scene is additively loaded prior to all other scenes, so that the singleton UIManager class is available to all subsequently loaded scenes and their entities. Then when the entity is first instantiated or woken up it self registered a callback with the UI Manager for the specific UI entity or instance.
     
    Shack_Man likes this.
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,748
    +1 for mentioning additive scene loading... it takes a teeny bit of extra thinking and setup but pays HUGE dividends. In fact, I have committed other feverish scribblings about it here:

    Additive scenes are one possible solution:

    https://forum.unity.com/threads/right-way-for-performance-divide-scene.1023673/#post-6630961
    https://forum.unity.com/threads/right-way-for-performance-divide-scene.1023673/#post-6754330

    https://forum.unity.com/threads/problem-with-canvas-ui-prefabs.1039075/#post-6726169

    A multi-scene loader thingy:

    https://pastebin.com/Vecczt5Q

    Other notes on additive scene loading:

    https://forum.unity.com/threads/removing-duplicates-on-load-scene.956568/#post-6233406

    Timing of scene loading:

    https://forum.unity.com/threads/fun...ject-in-the-second-scene.993141/#post-6449718
     
    Shack_Man likes this.
  5. Reahreic

    Reahreic

    Joined:
    Mar 23, 2011
    Posts:
    254

    It's super helpful especially when working in a team where the UI dev needs to edit (and check in) UI elements that would otherwise be part of the checked out scene you're currently adding functionality to. (Unity single scene projects and git/svn don't merge nicely)

    Also comes in handy when baking, especially when you have multiple scene chunks that can be baked independently of each other. I'd hate to have to re-bake an entire level when just one corner of it was changed, and that corner can't be seen by or doesn't affect the other level 'chunks'.

    It also comes in super handy with a singleton that manages object references using a GUID, which allows for cross scene editor linking and working around the current inability to assign editor references to objects in another scene.
     
    Shack_Man and Kurt-Dekker like this.