I have a menu screen with buttons to load the current save file, start a new game, or quit the game. All three of these buttons work fine when the game is first started, but once you go to another scene and then return to the menu, the load game button no longer works. The button is still registered as being pressed (it still highlights) but the method that’s supposed to happen when it’s pressed isn’t being called. This happens regardless of which method is assigned to the button.
The script that holds the methods to be called when the menu buttons are pressed is in a game object marked as dontdestroyonload, so any time the menu scene is loaded after the game starts up I am assigning the buttons their listeners via the following script:
In general, DO NOT use Find-like or GetComponent/AddComponent-like methods unless there truly is no other way, eg, dynamic runtime discovery of arbitrary objects. These mechanisms are for extremely-advanced use ONLY.
If something is built into your scene or prefab, make a script and drag the reference(s) in. That will let you experience the highest rate of The Unity Way™ success of accessing things in your game.
“Stop playing ‘Where’s GameWaldo’ and drag it in already!”
Here’s why all this stuff is CRAZY code:
If you do insist on persisting with the GameObject.Find() nightmares, you have to debug it to figure out where your assumptions are failing. The list of places in the above link can help you get started, but remember that timing problems can be very tricky to reason about!
By debugging you can find out exactly what your program is doing so you can fix it.
Use the above techniques to get the information you need in order to reason about what the problem is.
You can also use Debug.Log(...); statements to find out if any of your code is even running. Don’t assume it is.
Once you understand what the problem is, you may begin to reason about a solution to the problem.
Remember with Unity the code is only a tiny fraction of the problem space. Everything asset- and scene- wise must also be set up correctly to match the associated code and its assumptions.
I appreciate the response and the advice! I do have the events for these buttons assigned in the inspector, but the object that this script (which is also the script containing the button events) is attached to is marked dontdestroyonload, so when I return to the menu scene after having gone to a different scene the buttons no longer recognize those events, which is why I’m trying to reassign them in the inspector. This has worked for every other button except Load. If you have a better way to do this that takes into account the changing scenes, I’d welcome it!
I’d used debug mode and Debug.Log() in the process of trying to determine the problem but I’ve actually just figured it out-- I’d used the same name for two buttons. Doesn’t it always seem to be the simple answers that take the longest, lol. Even with that fixed, if you’ve got suggestions as to how to avoid using GameObject.Find(), I’m all ears
Anything DDoL should A: never start in a scene, and B: never hold onto a reference to anything in a scene. As soon as the scene unloads, and is loaded again, those are different instances of the objects, and your previous references are now pointing to destroyed game objects.
Trying to hack around this by reestablishing the references isn’t going to scale either.
Though I’m not sure why any of this main menu stuff needs to be persistent in the first place. It can just live in its own scene, and potentially call other systems to load, settings, quit, etc.
Yeah that’s fair! It was a long and roundabout process figuring out the save/load system in conjunction with changing scenes and this was the eventual solution I came to, but I’m working now on straightening it up, getting rid of unnecessary bits, etc, which includes figuring out how to work around dontdestroyonloads. I’m taking your advice and trying to ensure I’m not starting them in a scene as well. Thanks!