Skip to content

Repository files navigation

Manager<T>

Tired of writing singletons? Hate having 30 managers cluttering every scene?

Manager<T> is a tiny Unity framework for persistent, scene-aware manager singletons. Write your manager once, drop it on a prefab, add it to one list — and it spawns itself, survives every scene load, and gives you a clean Instance accessor. No boilerplate, no DontDestroyOnLoad copy-paste, no manager objects sitting in your scenes.

public class AudioManager : Manager<AudioManager>
{
    protected override void Init()   { /* one-time setup */ }
    protected override void ReInit(string fromScene, Scene toScene) { /* per scene change */ }
    protected override void Delete() { /* teardown */ }
}

// anywhere in your game:
AudioManager.Instance.PlaySfx(clip);

That's the whole thing. No singleton plumbing to write, ever again.


Why this exists

The usual Unity manager looks like this, copy-pasted into every manager you own:

public static FooManager Instance;
void Awake()
{
    if (Instance != null) { Destroy(gameObject); return; }
    Instance = this;
    DontDestroyOnLoad(gameObject);
}

Then you drag a FooManager object into every scene, hope you didn't forget one, and end up with a bootstrap scene full of thirty manager GameObjects. Manager<T> replaces all of that:

  • The singleton is written once, in the base class, using the CRTP pattern (class FooManager : Manager<FooManager>). You never write Awake, Instance, or DontDestroyOnLoad again.
  • Managers live on prefabs, not in scenes. They're listed in a single ScriptableObject and spawned automatically before the first scene loads.
  • A scene-change lifecycle is built in. Override ReInit and your manager reacts to every scene load — swap music, reset state, refetch references — without wiring up scene events yourself.

Coming from Godot? This mirrors Godot's AutoLoad (singleton) workflow: you register a node once in a central list, the engine spawns it automatically at startup, it persists across scene changes, and you reach it by name from anywhere. Here the "AutoLoad list" is the ManagerList ScriptableObject and the global handle is YourManager.Instance. If you've built autoloads in Godot, this flow will feel immediately familiar.


Installation

Install via Unity Package Manager (Window → Package Manager → + → Add package from git URL), or add it to your manifest.json:

"com.playermadegames.managerst": "https://github.com/16Byte/ManagersT.git#v1.0.0"

Dependency: ManagersT requires com.pmg.utilities (it uses SceneEvents for the scene-change hook). Make sure that package is installed too.

Requires Unity 6000.0 or newer. Recommended Unity 6000.3 LTS


Getting started

1. Write a manager

Derive from Manager<T> using your own type as T (this is the CRTP trick that gives you a strongly-typed Instance for free):

using PMG.ManagersT;

public class GameManager : Manager<GameManager>
{
    public int Score { get; private set; }

    protected override void Init()   => Score = 0;      // runs once, at Start
    protected override void Delete() { }                // runs on teardown

    public void AddPoint() => Score++;
}

You override three hooks instead of Unity messages:

Hook When it runs Notes
Init() Once, on Start() after the singleton is claimed Your one-time setup. Required override.
ReInit(fromScene, toScene) On every scene change Optional. Scene-aware reset logic.
Delete() On destroy, for the live instance only Your teardown. Required override.

You never write Awake, OnEnable, Start, OnDisable, or OnDestroy yourself — the base class owns them. They're protected on purpose: if you accidentally re-declare one, the compiler flags it (CS0108) instead of silently breaking the singleton.

2. Put it on a prefab

Create an empty GameObject, add your manager component, and save it as a prefab (e.g. GameManager.prefab). Delete the GameObject from the scene after saving — the framework will spawn it for you on Step 4.

3. Register it in a ManagerList

Create the list asset via Assets → Create → PlayerMadeGames → ManagersT → ManagerList.

  • Name the asset Managers and place it at Assets/Resources/Managers. (The bootstrapper loads it by that name from a Resources folder.)
  • Drag your manager prefabs into the Managers list. (Prefabs, not scripts — the bootstrapper instantiates each entry's GameObject.)

4. There is no step 4

When you enter Play mode, ManagersBootstrapper runs automatically ([RuntimeInitializeOnLoadMethod(BeforeSceneLoad)]), instantiates every prefab in the list, and each one claims its singleton and marks itself DontDestroyOnLoad. Access any manager from anywhere via GameManager.Instance.


The scene-aware lifecycle

The reason ReInit exists: managers usually need to react to scene loads, not just survive them. A persistent AudioManager that keeps the same AudioSource alive across scenes still wants to swap the track when you move from the menu to the level.

protected override void ReInit(string fromScene, Scene toScene)
{
    PlayMusicForScene(toScene.name);
}

ReInit only fires on actual scene changes — it's suppressed on the very first load (where there's no meaningful "from" scene), so Init() owns first-scene setup and ReInit owns everything after. Because the initial activeSceneChanged event is inconsistent in Unity, the recommended pattern is:

  • Init() handles the opening scene.
  • ReInit() handles every scene change after that.

See the Audio Manager Example sample for a complete, working implementation of all three hooks across two scenes.


Samples

Import via Package Manager → PMG ManagersT → Samples:

  • Audio Manager Example — a full Init / ReInit / Delete lifecycle that swaps the soundtrack per scene across two demo scenes.

Notes & gotchas

  • Mis-wired CRTP is caught loudly. If you write class Foo : Manager<Bar> by mistake, the framework logs a clear error and disables that singleton rather than throwing or silently misbehaving.
  • Duplicates self-destruct. If a second instance of a manager is ever created, it destroys its own GameObject and leaves the original untouched.
  • OnDestroy is sealed. You can't accidentally override it and forget base.OnDestroy() (which would leak the static instance). Use Delete() for teardown.
  • No ManagerList found? If Assets/Resources/Managers is missing, the bootstrapper logs an error and spawns nothing — your game runs, just without managers.

License

MIT. See LICENSE.md.

About

Tired of writing singletons? Hate having 30 managers cluttering every scene? Manager<T> is a tiny Unity framework for persistent, scene-aware manager singletons. Write your manager once, drop it on a prefab, add it to one list — and it spawns itself, survives every scene load, and gives you a clean Instance accessor.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages