Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Advice for keeping references to a central class

Discussion in 'Scripting' started by smallstep, Apr 2, 2018.

  1. smallstep

    smallstep

    Joined:
    Jan 25, 2016
    Posts:
    34
    TL;DR: I'm thinking of replacing singletons with a referencing practice that keeps refs to critical objects (managers / logic holders) in a central class with static vars (objects are being auto-registered onEnable there and are then accessed easily from anywhere). Is this battle-tested? Any known caveats?


    Hi, I'm new to Unity (and C#) and for the last few days I'm trying to design the architecture for some games I want to port from other engines. These are simple 2d mobile puzzle games with 2-3 scenes and about 30 unique objects in each scene. What I find difficult to handle in unity is the right objects-communication architecture. I have considered singleton managers and events, but none satisfies me as a solution.

    I best like the referencing solution. Simple and more near to the native unity-way of doing things.

    However I feel that getting all those references in the start of each script is a waste of time and effort. I am thinking of a simpler solution that involves a "References" class with static fields (a static var for every major object in the game) and having each object assign itself in the proper static var onEnable and nullify the reference onDisable. This way we could reach everything from anywhere with minimum setup code.

    Of course, I can see how much coupling this practice could silently bring to my code, but I dont really care because the objects' logic is not going to be reused in other games and the more generic scripts will not have references to a specific-game's objects.

    What bothers me is whether this technique is going to work in practice. Is this something known and widely used / battle tested? Are there any known caveats I should consider beforehand?

    Thanks in advance for any advice!
     
  2. TJHeuvel-net

    TJHeuvel-net

    Joined:
    Jul 31, 2012
    Posts:
    818
  3. smallstep

    smallstep

    Joined:
    Jan 25, 2016
    Posts:
    34
    Singletons are giving me the luxury of global state so they are ideal for holding the generic managers (scenes / data / audio management etc). However I have a lot of somewhat unique (and not destroyable) objects which are always on scene. I am reluctant to make them also singletons (I guess having 50 singletons in the scene is not wise) and if not singletons I wonder how I'll have these objects communicating with each other. References are ok but there will be a whole web of links that I am wondering how to simplify. So I guessed a central registry would be a solution.

    I am going to study scriptable objects, thanks! The problem is that I am new to c#/unity and I supposed there would be a get started / friendly way to start developing things with. For the last month, whatever architecture I consider I find people criticize it to death for serious reasons (references, singletons, events, DI etc). This is a sign of freedom and plurality in development path, but also a very demotivating factor for a newbie like me. :)
     
  4. Errorsatz

    Errorsatz

    Joined:
    Aug 8, 2012
    Posts:
    555
    Sounds like a form of Service Locator. While it does introduce coupling, IME it works fine for situations where you're not trying to make something highly configurable/reusable.

    The somewhat more flexible version would be to have the classes in question implement interfaces, and then store references to those interfaces rather than the concrete class. Makes it easier to switch out components in future. You can also use a generic access method by type (ie. Services.Get<IScoreService>() rather than Services.ScoreService), which will make it easier to add more services in future, although at the cost of making the required services less explicit.

    Personally speaking, I've found that if you're willing to re-factor as needed to keep the code clean, it's better to use a simple solution and only make it more dynamic at the point when you have the need for that. Obviously that's not a hard and fast rule - in some cases the more flexible version is close to equally simple, or you know for a fact that configurability will be required later, and in that case you might as well do it right from the start. But overall, the added complexity of maximum flexibility has a cost (not primarily the cost of writing it, more importantly the cost of easily following the flow when you need to debug it a year later, or time spent getting new team members up to speed), and shouldn't be automatically used.