1

I'm trying to create a class hierarchy such that I can have:

SpecificScreenController < ScreenController < Singleton

So far I have these set up as:

public abstract class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
    private static T _instance;
    public static T Instance{ get{... return _instance;} }
}

public abstract class ScreenController<T> : Singleton<T> where T : MonoBehaviour
{
    public GAME_SCREEN GameScreen;
    //many more ScreenController common properties/fields/methods
}

public class SpecificScreenController : ScreenController<SpecificScreenController> 
{
    //subclass specific properties, overriden ScreenController methods etc.
}

This way I can use SpecificScreenController.Instance.GameScreen; This works, so far, so good.

What I want to now do with this is, for instance:

List<ScreenController> screenControllers = new List<ScreenController>();
screenControllers.Add(SpecificScreenController.Instance);
ScreenController s = screenControllers.Find(i => i.GameScreen == GAME_SCREEN.THING);

But, of course ... this won't compile because ScreenController now requires a Generic Type etc. What idiom can/should I use to preserve the Singleton behavior and ScreenController sub/superclasses ?

5
  • 2
    Jon Skeet's blog post on C# Singletons. More than you ever wanted to know about creating Singletons in C#. Commented Feb 17, 2016 at 0:48
  • FWIW, it seems to me that if you want List<ScreenController>instead of List<ScreenController<MonoBehaviour>>, then you shouldn't be inheriting from MonoBehaviour. Commented Feb 17, 2016 at 0:49
  • @RobertHarvey interesting read thanks ... the pattern I'm using is as it is for use in the Unity game engine where some properties of MonoBehaviour are getting used to deal with lifecycle events of the singletons. For now I'm stuck inheriting from it but (I assume) this is a generic(heh) question related to nesting generic classes. Commented Feb 17, 2016 at 0:53
  • You absolutely cannot, realistically, use singletons in Unity. It goes completely against the grain - it never works. This is a very basic fact about Unity. Commented Feb 17, 2016 at 19:00
  • stackoverflow.com/a/35891919/294884 Commented Jul 14, 2016 at 17:37

2 Answers 2

1

The problem here is one of covariance. You're assuming that if SpecificScreenController inherits from MonoBehaviour then ScreenController<SpecificScreenController> also inherits from ScreenController<MonoBehaviour>. It doesn't. You can't do this cast.

Sign up to request clarification or add additional context in comments.

10 Comments

Hi thanks for confirming the issue, really just looking for ways to work around / more elegantly set this up now!
@BenRoberts - No worries. What are you trying to achieve by casting to ScreenController<MonoBehaviour> anyway?
specifically I want to have a List of ScreenController subclasses I can iterate over in order to work out which one should be current, which to hide/show etc.
Then you should make all of the classes implement an IScreenController<MonoBehaviour> interface. Then you can make a List<IScreenController<MonoBehaviour>> easily.
I think the issue with this route is that ScreenController has a bunch of fields which the subclasses use ... where would those go?
|
-1

As there seem to be no really clean solutions to this issue I ended up removing Singleton from my class hierarchy and copy-pasted non-generic versions of the singleton property get/instantiate code into each of the classes that I wanted to be singletons.

public abstract class ScreenController : MonoBehaviour
{
}

public class SpecificScreenController : ScreenController
{
    private static SpecificScreenController _instance;
    public static SpecificScreenController Instance{ get{... return _instance;} 
}

10 Comments

I can assure the clean solution is: it is nothing more than a GameObject (and some component on it) .. which you want to access everywhere. Just do that with syntactic candy, such as stackoverflow.com/a/35524924/294884 FindObjectOfType. That is utterly clean, and 10000% ECS. GameObjects are singletons in ECS, every "thing" in a scene is a singleton totally inherently. The "search for singletons" in Unity is a "forest for the trees" confusion. To handle "central services" (say, "sound effects") is the very raison d'etre of ECS, what they do. There's no "search for a solution."
using FindObjectOfType is a terrible 'solution' ... This is what the Unity docs say about it: "Please note that this function is very slow. It is not recommended to use this function every frame. In most cases you can use the singleton pattern instead." docs.unity3d.com/ScriptReference/Object.FindObjectOfType.html
what are you referring to? obviously you use FindObjectOfType once in Awake. "It is not recommended to use this function every frame" why would you use it every frame?
IMHO your 'preloader' scene concept is more overhead and less usable than just using singletons. It's certainly possible to do and seems to fit with your personal beliefs about singletons in an ECS framework but I just don't share those beliefs.
There can be no such thing as singletons in the ECS concept of Unity, it's not possible. There is simply no way to meaningfully say that a GameObject is a "singleton", it is a meaningless concept. Imagine if you said you were going to have, oh, a "singleton scene". It doesn't even mean anything. You would essentially be saying "well I'm going to have a project, and we're going to ensure it has only the one scene". Similarly applying the term "singleton" to a GameObject just doesn't make sense. Technically it is absolutely impossible (apart from that it would be "whacky") to have only one..
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.