Not quite. The rooms manager is absolutely not in charge of getting the sprites. It is simply a data container and the only logic it contains is broadcasting events to let subscribers know when its data is modified.
how it works
This might be a bit tricky to grasp initially. To simplify things, pretend we have class A, B and C. For the sake of making this a bit more concrete, pretend we’re trying to display a timer on the screen that goes from 60 to 0.
Class A is a data container and nothing else. It contains the timer variable and has no logic that operates on its data. The only logic it contains is broadcasting events to let interested classes know when its data has been modified.
Class B contains operating logic. Its purpose is to modify the data of Class A. In this case, it could be a coroutine that brings down Class A timer from 60 to 0 over 60 seconds.
Class C’s purpose is to give the user a visual representation of the data (the timer on the screen). In this case, it could be strapped to a gameobject that contains a UI text component. Class C will hook onto Class A’s event to be notified when its data is modified.
What will happen is Class B will progressively change the values of Class A. Class A will broadcast an event when its data is modified. Class C will be notified and will display the timer accordingly.
In this case, Class C will modify its text component to reflect the timer value and it could also animate the transform a bit to give it life.
The example above is obviously overkill for that scenario but should give a good idea of how the pattern works.
For you, you were talking about prefabs, so I’m guessing your rooms aren’t procedurally generated. It’s really hard for me to help you with a concrete implementation without knowing exactly how your rooms/maps are built.
Ideally, you would create a “Room” or “Map” container class/file that would contain the initial position of every game elements in the map and all the relevant goodies. How you do this is up to you. You should have as many instances as you have maps/rooms.
Then, you should have a controller class that’s responsible for handling the flow of the game. It passes whatever map you want to load to the model class (that’s Class A in my explanation) when you want to load a new map/room.
When you do that, the model will notify everyone who’s interested that the map has changed.
Remember Class C in my example who was responsible for displaying the timer? You need the equivalent of that. We’ll call it MapView. MapView hooks onto the model and as soon as the map changes, its responsible for clearing the old map on the screen and displaying the new one.
It does that by reading the data from the model to figure out what goes where and then recreates the map. So, to answer that last question of yours, your map probably shouldn’t be a big prefab, and yes, you should instantiate the sprites. Better yet, pool a bunch of objects with sprite renderers and just assign the right sprites.
Furthermore, you could hook an additional view for your enemies. Hook it to your model and when the map changes, its responsible for reading the data and clearing/displaying your enemies. etc.
That’s the cool thing about this pattern, the model(data container) doesn’t have to be aware of the existence of the views. You can hook/delete as many views as you want and you’ll never run into a coupling problem. You just create/hook a bunch of stuff based on the visual information you want to provide to your user, as long as the model holds the proper data (that could be the map, the enemies, the character, anything you want, really!).
You can get really deep with this stuff, or use it simply for the map, or not use it at all!
If you’re not snoring yet, consider that this may also not be the best implementation for your use-case. It’s only one implementation that has its pros and cons.
Hope that helped more than it brought confusion.