0

I have a situation where I have levels in my game and a start screen. For the levels, there is a persistent empty GameObject. My code for setting the game over and level complete canvases active (Also button initializations eg. restart, quit, next level...)is attached to that empty game object. Further, the canvases mentioned are attached to the persistent object.

Would converting my persistence script into a singleton script be the best way to manage the behavior so that the canvases don't land up on the start screen (and unnecessarily slow the game) when I quit a level? I am planning on putting the persistent object in every level to test each level specifically.

As of right now this is what I'm planning on doing unless there are better patterns or suggestions. Any help would be appreciated!

     if (instance == null || (SceneManager.GetActiveScene().name != "StartScreen"))
    {
        instance = this;
        DontDestroyOnLoad(gameObject);
    }
    else
    {
        Destroy(gameObject);
    }
shanksVR
  • 15
  • 4
  • It looks like you already have a potential approach in mind. Have you observed any particular problem or dissatisfaction with this approach, to give a specific axis on which answers can seek to improve it? – DMGregory Jun 21 '23 at 04:27
  • I wanted to see if there are better approaches for handling the behavior I described so that I could try them out and maybe learn the perks/downsides. This is my first attempt at making a game so I am mainly trying to figure out how things work. Reflecting on it the question is quite vague and difficult to respond to. Should I delete it? – shanksVR Jun 21 '23 at 05:19
  • My advice for the first game: focus on finishing it first. There is always some code that can be further improved, made faster, more general or optimazed. As long as you don't notice some horrible lag spikes, don't worry too much at the start and just use the first thing that comes to your mind. – Zibelas Jun 21 '23 at 06:06
  • @Zibelas Got it, I'll try to follow through on that. It's just really hard to stay focused cuz there is so much going on (With unity in general). I have gotten to the point where I know enough to come up with ideas but not enough to do exactly what I want. But I guess I just gotta suck it up and keep it going. Thanks! – shanksVR Jun 21 '23 at 06:25
  • Just one small suggestion, since your SceneManager is a singleton and you carry it to each level, don't hardcode on which scene it can be created. Maybe later you rename your StartScreen scene. Or for debugging purpose you try to load a scene directly. You can find here some extra examples and the differences: https://gamedev.stackexchange.com/questions/116009/in-unity-how-do-i-correctly-implement-the-singleton-pattern. Or you want to have it on the StartScreen because the background gets a preloaded level preview. – Zibelas Jun 21 '23 at 06:38
  • If it is only because of performance then don't worry way to much about it. It is more likely you ending up with messy code than with slow one. Btw you can try ManagerScene that is always loaded instead of persistent objects that you juggle between scenes. – Nikaas Jun 21 '23 at 08:36
  • Singletons are actually quite a PITA in Unity... Issues range from the constructor not being called from the main thread (so you can't interact with most of the Unity API) through issues managing the lifecycle, especially in the editor [You probably don't always want your singleton persisting between presses of the play button]. There are ways around all of the above, but I'd never reach for a singleton as the first solution. – Basic Jun 21 '23 at 11:03
  • @Zibelas Thanks for the resources, I will look into them! And for the suggestion --> Should I be using the build no. instead? – shanksVR Jun 21 '23 at 20:41
  • @Nikaas Thanks! I am using a singleton gameManager to handle moving between scenes (I think that was what you were referring to by the ManagerScene)! When I asked the question I was under the impression that singletons were primarily for easier connectivity because a few forums said initializing a reference to a script every time would be a bad approach. So, I was not sure it was the best way to handle persistence and duplication! – shanksVR Jun 21 '23 at 20:43
  • If you guys don't mind I have a follow-up question. I have the persistence script attached to an empty game object. Further, the canvases that I want to remain are attached to that game object. This object has been added to level one. I have a level selection screen in the start menu. I want the user to be able to go to level 2, without loading level one if it has been unlocked. Would it be better to save the entire object as a prefab and instantiate it when a level is selected or should I add the singleton script (formerly, the persistence script) to each scene? – shanksVR Jun 21 '23 at 21:02
  • @Basic Thank you! I think I messed up my project a month ago because of this --> I had put a lot of things in my gameManager (Handling the button behavior and other things) and I crashed my game when I moved to another scene (At the time I didn't make the objects that it was referencing persistent). By setting up the singleton so that it is in a completed state without the inspector (This is where the APIs come in... right?), would it not be safe to use? Also, by moving or copying the start functions to an onSceneLoaded function, would it handle the constructor not being called? – shanksVR Jun 21 '23 at 21:21
  • @shanksVR If you have another question, it's best to ask a new question, but to deal with my comments: By "Unity API" I mean everything from GameObject.Find through Time, to almost anything else in the UnityEngine namespace. Pure C# is fine. Anything that interacts with the scene, engine or other gameobjects will fail. Even if the object isn't marked "Run in inspector", when you launch the game, it'll be loaded into memory and -because the .Net runtime is never unloaded- will persist there across runs. You can get around this with some AppDomain fanciness, but as I said... PITA. – Basic Jun 21 '23 at 21:46
  • @Basic Will do, no more questions on here from me. This is a bit beyond me... I think I'll get back to this when I'm a bit more learned, thanks again! – shanksVR Jun 21 '23 at 22:04

1 Answers1

1

I would stick with what you have. If it works, it works. Only make changes if you notice a problem or something that is making development in other areas difficult.

You mentioned you are worried about performance. Did you measure it? Is there actually an issue? Did you confirm that the issue is coming from this system? Only worry about performance when those 3 things have already been determined.

Now to get back to your original question. I think your proposed solution looks fine. For a small or medium sized game that’s probably all you need. If you need to massively scale up your game, I would look into using additive scene loading. And keep a persistent scene around in the background with all the persistent objects/UI on them. That way you only load them once and know they’ll always be there.

But. Like I said. Only look into this if you start seeing problems with your initial approach. As the commenters said. Better to finish a game then to have a well designed unfinished game.

Adam B
  • 800
  • 3
  • 14
  • Thank you! I'll hold off on worrying about performance until after I am done - I was definitely on track to not completing it haha. – shanksVR Jun 21 '23 at 21:07
  • Haha join the club! I am a member of that club with many projects :). If you feel like the answer answered the question please accept it so future users can learn from your question :) – Adam B Jun 21 '23 at 21:34
  • I'll do my best to get kicked out of the club then, haha. Got it, thanks again! – shanksVR Jun 21 '23 at 21:52