3

I'm rather new to Unity, and C# too as a matter of fact!

What I am doing right now is:

  • I have a "Singleton" (it's not really a Singleton but that's not the point) GameObject called GameManager, to which is attached my GameManager.cs script containing most of the game info (which tutorial text has been already displayed, functions to load localized text, last scene loaded...)
  • As children of this GameManager object, I have different kinds of GameObjects I do not want to destroy on load either, such as PostProcessing Profiles, Global Lights, Audio Manager, UI Canvasses (canvi?) and other things...

There are plenty of great tutorials on Unity, and it's an awesome community, but I could not really find any info on Unity's "best practice" regarding GameObjects management.

Is this a correct way to proceed? Will I have issues in the future with this method? Should I make a generic class that implements Unity's DontDestroyOnLoad() and have the Object I want to keep inherit from that class? Is there a better way?

It works fine for now, but I want to be sure I am not doing this the wrong way and potentially messing up with my game's performance or stability.

Many thanks in advance.

Rom
  • 386
  • 3
  • 11
  • 2
    Have a look at this: https://gamedev.stackexchange.com/questions/116009/in-unity-how-do-i-correctly-implement-the-singleton-pattern – landings Jan 14 '20 at 03:00
  • This is quite opinion based since it is even quite [controversial](https://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons) **if** the singleton pattern should be used **at all**! Unity's `DontDestroyOnLoad` makes it quite tempting to start using singletons all over the place, and yes sometimes you somehow need at least one which in my opinion then should control all the rest. Don't use multiple ones! – derHugo Jan 15 '20 at 06:58
  • 1
    The Singleton pattern itself is not best practice. It is considered anti-pattern for a very good reason. Singleton is not required at all. If you are writing a testable and extensible software you should prefer to follow the Dependency Injection pattern. This way you can inject shared instances into relevant classes. This enables all benefits of a Singleton without all the disadvantages that come with a Singleton (e.g., you can't mock static code). The downsides of the Singleton patter are facts and not opinion based. – BionicCode Jan 15 '20 at 21:07
  • 1
    If you still can or should use this pattern despite the negative facts is opinion based indeed. If you can pay the price (live with all the downsides) you are probably good to go. As frameworks like [MEF](https://docs.microsoft.com/en-us/dotnet/framework/mef/) are very easy to use, Singletons may never be worth the price. MEF is a powerful and easy to use framework that enables Dependency Injection and lifecycle management. – BionicCode Jan 15 '20 at 21:07
  • @BionicCode Singleton pattern has a lot of problems. But to suggest that DI is better is to ignore the context: this is for Unity3D. DI is a terrible match for Unity3D, both because of the apps being created (games), and the API frameworks available (which are moving to DOTS). – Adam Apr 03 '20 at 04:05
  • @Adam That's why games are crappy products. I hear that every day, games don't need this and don't need that. You can read lots of useless blogs about it. Unit tests are not for games(?!). Fact is, most games won't sell, if the customers were business oriented and _rely_ on quality or reliability. Games just have to look fancy to get sold. No one cares to sell buggy applications in the game industry today. – BionicCode Apr 03 '20 at 11:09
  • @Adam Because you as a game developer are willingly following this paradigm doesn't mean it is right. Games are software too. Applications like every other application. Games definitely are not superior software products, where common rules don't apply (appears you are trying to sell it like this). I think it's a pure business decision to avoid common patterns and architectures for the sake of faster and cheaper releases to maximize revenue, only possible in a market, where quality of a software product is just perceived as _"looks good - will buy it"_. – BionicCode Apr 03 '20 at 11:09
  • @Adam My main statement was _"If you are writing a testable and extensible software you should prefer to follow the Dependency Injection pattern."_. If somebody don't need this, he is free to use what ever he needs. Even Singleton. It always depends on the requirements. Decisions like this should be based on requirements. Don't get me wrong. I am just arguing that using a modern DI framework makes replacing Singleton so cheap and very easy. No need to limit developer flexibility/agility because of the choice to use Singleton throughout the application. – BionicCode Apr 03 '20 at 11:39

2 Answers2

1

There are two best-practices here.

  1. Build lots of singletons, and replace Unity's built-in initialization system

  2. Build very few singletons, and work within Unity's initialization system, and make heavy use of the new Multi-Scene Editing system.

Option 1 is very popular with game-studios and professional gamedevs, who are skilled at doign this and have done it many times before. The main problem is that once you start down this route you are comitting to maintaining your own parallel init system. The main advantage is that your system is probably better, definitely more powerful, and usually faster (!) than Unity's internal one.

Option 2 is more popular with people new to game programming, who want to lean on as much of Unity's built-in features as possible.


That said, there are some strange things in your question.

For instance ... Canvas? Why on earth would you be trying to make Canvas into a singleton? This suggests you're misusing Canvas in a big way (and probably some of the other classes).

The standard approach (and the only one that Unity supports) is for every Scene to have its own unique Canvas. To do something different ... is very odd.

I suspect you've misunderstood what "DontDestoryOnLoad" does. It does not prevent things being destroyed on load!

Instead, it prevents being destroyed when a NEW scene is being loaded, and they only lived in the OLD scene. A much better name would have been: "DontDestroyWhenLoadingANewScene"

There are a lot of bugs (going back many years) in Unity with DontDestroyOnLoad, so in general its best to avoid it as much as possible. For simple cases it works fine, but if you use it too much you run into complex edge cases and interactions with Unity's own internal classes.

Adam
  • 32,197
  • 16
  • 119
  • 146
  • I wonder what _"skills"_ you need to implement a Singleton. Every first grader in computer science can and actually does this. Replacing the built-in bootstrapping - ok. But Singleton? You should admit that this is just the paradigm to write "dirty" code in favor of a quick release. It's a trade-off to maximize the revenue in a market where the customers don't care about quality. Keep things as simple as possible. Big players in the game industry are not interested in maintaining their products once they are released. After the release they start a new project. – BionicCode Apr 03 '20 at 11:18
  • I also argue, that Singletons make _"your system is probably better, definitely more powerful, and usually faster"_. Singletons tend to pollute your memory. But I agree, with today's machines memory size, it is not an issue. Same applies to the small overhead that IoC implementations have compared to the antique Singleton. It's negligible. The only advantage Sigleton pattern has is the simplicity. They are easy to understand as there is no complexity attached to them. _Implementation_ of software based on Singleton is very simple. _Maintenance_ isn't. That's why (game) project owners like it. – BionicCode Apr 03 '20 at 11:31
  • @BionicCode Have you ever implemented a TRULY thread-safe singleton? Nearly every (Computer Science graduate!) gets this wrong, and its a serious, data-corrupting, long-term bug that will eventually cause you huge problems. In Unity3D specifically: have you ever implemented a CORRECTLY INIT'D Singleton, that understands the Editor's Static-Init system, that respects Unity's custom startup order (both in Editor and Runtime - they are incompatible!), and supports Multi-scenes without corruption? Oh, and you got PrefabStageMode correct, right? *all these require extra code in your singleton* – Adam Apr 09 '20 at 09:11
0

Obligatory utopic programmer answer: Try to avoid using singletons as much as possible.

That being said, feel free to use my singleton implementation, been using it for years in production and it works fine.

https://gist.github.com/ronrejwan/7a4f0037effec3c9e8943542cf9cfbc9

Ron
  • 1,461
  • 3
  • 13
  • 28