1
\$\begingroup\$

What are some proven and preferable patterns to realise multiple "screens" in the game? Not in the sense of displays (monitors) but "views" within the application.

Say it's a Civ/Heroes-type game. We will typically have these screens during the proper gameplay:

  • Main map (strategic)
  • Battle map (tactical)
  • City management screen
  • Research screen
  • etc.

As you can see, some of them are UI-like in nature but some are full-blown interactive scenes.

We need to be able to:

  • Quickly switch between them
  • Keep a global game state between them (e.g. the (in-)famous GameManager instance must stay intact)
  • Bonus points if able to make a fancy transition (e.g. city screen rolling down from above)
  • Bonus points if able to keep one screen (e.g. city screen) only partly covering another (e.g. the strategic map) and both are animated

Theoretical solutions I can imagine (I'm still a Unity noob):

  • Separate scenes for each screen. But will the engine be able to switch between them fast? (I read that a scene is akin to a "level" in a traditional game, which usually means a loading time?) Also, how will I track the global state (GameManager)? Can I overlay one screen over another?
  • Everything in one Unity scene but multiple cameras looking at different objects, with switching between them or nesting. E.g. one camera looking at the map grid, another at a city screen etc. But then I run the risk of objects from one "scene" (only virtually) affecting others (e.g. lights or particles) unless I place them sufficiently far apart.

Is any of my ideas going in the right direction? Is there a better pattern that I'm missing?

\$\endgroup\$
1
\$\begingroup\$

The intended solution would be to use a different scene for each of these "views". You can have multiple scenes loaded at once by using SceneManager.LoadAsync with the parameter LoadSceneMode.Additive. However, loading a complex scene while the game is running can cause notable loading times. One popular Unity game which is plagued by that issue is Kerbal Space Program.

An alternative option would be to have each of these views in your scene at the same time, but wrap each of them in an own game object. You can then activate and deactivate these objects as needed. This is less memory-friendly, because no matter what the player does, all views are constantly kept in memory. But inactive views shouldn't consume much CPU power, because deactivated game objects are relatively cheap in this regard (not free, though).

Interactions between the different views can be avoided by putting each of them on a different layer. Set the physics collision matrix so that each layer only collides with itself. Use a different camera for each view, and set its culling mask to only render the view the camera is for. If you want to render multiple views at the same time, use the camera Depth and ClearFlags to control in which order they are drawn to the screen.

When it comes to placing the views in your scene space, then you might still want to place them far away from each other to make editing easier. But you shouldn't have to worry about intersection effects during the game anymore.

If you want one view to include a cutout of a different view (like a rendered minimap), have the camera for the sub-view render to a render texture and integrate that texture into the host-view. An alternative solution is to change the camera's viewport to not cover the whole screen.

One thing which might get a bit frickly with this setup could be positional audio. Unity only allows one AudioListener in the scene, which you would usually attach to the main camera. When you want some game object to make noise, you would attach an AudioSource to it, and Unity would make sure the sound plays with the expected volume and stereo panning. But when you have multiple cameras in different locations rendering multiple views which all want to play 3D sound effects, then this is not going to work.

One possible solution could be to build an own audio system similar to the one I described in this answer. Build a separate "sound studio" section in your scene with an AudioListener. If you want to play a sound, spawn a new game object with an audio source near that listener to play the sound and remove it when the sound finished playing.

I'm looking forward to playing your game.

\$\endgroup\$
0
\$\begingroup\$

You appear to be treating all screens as the same; they are most likely not. What you really have are UI screens, and Maps that form the game world.

As you have pointed, many of these screens are UI like in nature. Thus, the obvious solution is these should be implemented as UI. This will also allow things like fancy transitions. This should be for things like the City Management screen, and Research screen ect. Have them start off screen, and swing into the map when clicked. Or as prefabs that get added to the UI when a button is clicked, and removed when clicked off. You can have UI elements have their own cameras, but just as easily implement something to add and remove, and move about, a single UI layer (or perhaps one per map).

Meanwhile, your "world" maps; the strategic and tactical maps, should be treated as part of the world space. As Philipp has suggested in his answer they should each have a parent GameObject that can be disabled and enabled (thus disabling the map entirely), and likely separate cameras, and place them on different layers to avoid physics interactions.

Finally, while Unity was originally intended to use Scenes for this, a large number of developers do not, and scene transitions can have issues with keeping data between scenes. I would not recommend using scene transitions for this, except maybe for transitioning between maps.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.