Issue with persisting scripts & Unity Events

So, I have a Game Manager object, to which I attach scripts that I want to persist from scene to scene. For the most part it works fine, but running into an issue using Unity Events.

I created a dynamic event to take a string argument in my character script. This is a Unity event. I drag the Game Manager object in as a listener and point to my method to decide how to handle scene changes.

However, doing this in more than my first scene is problematic. If I set up a Unity Event in my next scene, for example, I have to create the Game Manager object in that scene as well, or I cannot drag it into my player script to point to my handler method.

The script I’m using for scene management–I made into a singleton in the following manner:

  private void Awake()
    {
        if (sceneManagerInstance == null)
            sceneManagerInstance = this;
        else
            Destroy(this);
    }

So basically, the Unity Event works from the 1st scene to the 2nd scene, and because I needed to create a Game Manager in the 2nd scene in order to drag the object for the Unity Event there, this transition is destroying the script in the 2nd scene…and I think the persisting version of it isn’t translating. Any trigger to a different scene from then on does not work–but works fine if I start on the 2nd scene.

I prefer to take a pure-code approach to this using a singleton pattern. It is simply the most-expedient solution for 99% of all quick-game-dev uses.

Some super-simple Singleton examples to take and modify:

Simple Unity3D Singleton (no predefined data):

Unity3D Singleton with Prefab used for predefined data:

These are pure-code solutions, do not put anything into any scene, just access it via .Instance!

If you want to ever Destroy() it such as after the game finishes, just do:

Destroy(MySingletonThing.Instance.gameObject);

Thanks for the reply. I see what you’re saying, but my main focus was the Unity Event thing. I’m kinda leaning towards just using C# events while wondering why I’d ever use Unity Events lol. Originally, it seemed like a time-saver. All I’m really after is I wanted a single/separate script to handle scene changes, those changes being dictated by logic from an argument I’d pass w/ the event. That didn’t work since it seems like under the hood, the objects/scripts that we create in the editor are no longer the ones referenced if they are destroyed by the singleton pattern when coming from another scene.

I was interested in your idea, however (first one), about not putting the script in the scene. Didn’t know you could do that…and after trying it…I still can’t :p. I copied and pasted the code, renamed the script, etc…and I tried a couple debugging messages in the Awake() & Start() methods. Then I started my scene up, and nothing.

If I reference the “Instance” from another script that is in my scene, then everything fires off and it works fine…but even if I manually add the script to the execution order, it doesn’t fire if it isn’t referenced by something. So…in that light, it may as well be in the scene anyway? Is there something I’m missing there?

That’s correct. It’s intended for things that come into being and you don’t care a lot about the details of when they do, and you might want to destroy them later. Think GameManager, or LevelSequencer, or BossFightOrchestrator, that sorta thing. You do need to reference it to kick it off.

If you want something to change scenes on a button press (for example), just make a little script that takes a string and listens to the Button’s .onClick() method and when it fires, loads the next scene. You can make it as clever or as simple as you like… here’s one example:

https://answers.unity.com/questions/953437/button-onclick-load-scene.html

(Scroll down because the early responses are for the pre-scene-manager API).

Otherwise, I would just code the scene loads wherever you need them. I like to wrap the Unity scene loader in something that I find easier to use, but it’s just as easy to call the scene manager everywhere too.

I would also NEVER use the integer argument for specifying scene loading. That’s a legacy throwback system. Always use strings for your scene names. If you use integers and the editor list of scene changes, your code will be borked horribly.

Thanks again for taking the time. I checked out the links and got some good context :).

In my particular case, this is actually what I’m trying to avoid. Depending on the situation, I might be switching to/from side-scrolling screens or to/from an overworld map, which changes the prefabs I’m using, etc… So, I want all the “logic” for scene changing in 1 spot, or I’m afraid that I’ll later be cursing my way through a half dozen scripts :face_with_spiral_eyes::rage:.

I did end up using just C# events. I just create an scene change event of some kind in my character scripts, and when they hit ___ collider, raise my event and send the argument(s) to the scene manager script (which subscribe to those events, of course). Probably should have just done that to begin with, but I was curious about Unity Events. They’re nice, but like many “tools” which simplify programming, have limitations.

Speaking of tools, don’t overlook partial scene loading. That’s really a hugely powerful tool for managing game chunks in Unity. For instance the tank game I’m working on right now loads an overall master scene that never unloads, but then for each level it additively loads all the sub scenes it might need:

  • the player
  • the UI
  • the radar system UI
  • the content of the level
  • an enemy manager of a certain flavor

All inter-scene links are done by FindObjectOfType() and until everybody has what they need, nobody does anything. Like the player needs to find the spawn point manager type, which is located in the level content.

The trickiest part to deal with is that scenes are loaded at the END of the current frame, and nothing can be used until next frame.

When the wave is done, the wave manager is poked by the enemy manager, and then unloads all the transient scenes and loads up a “Here’s how you did” UI scene.