Unity is a powerful suite of tools (Project IDE, Code IDE, run-time) for game development.
I have explored many architectural approaches to game projects. Architecture is a hot topic in Unity — especially related to scaling up to larger Unity game projects.
My architectural background includes many frameworks. Highlights include heavy usage of Robotlegs (I event contributed to the project and drew the official diagram), PureMVC (I was the technical editor for the O’Reilly book on it), and PushButton (I published related articles for Adobe). I also presented and taught about the three at conferences and weekend workshops. Of these, only PushButton is a game-specific architecture, but all can be applied to games.
What are the qualities of a good gaming architecture? Most architects applaud solutions which are flexible, readable, D.R.Y., testable, orthogonal, and “refactorable” (at an acceptable cost). I will discuss the philosophy of design in a future post, but for now I simply list the major pros and cons of each approach.
Update: After completing all the research below, I created a new custom architecture for Unity 2019/2020.
Checkout Unity Game Architectures – Part 1 for more info!
Unity3D Bowling
What are the qualities of a good gaming architecture? Solutions which are flexible, readable, D.R.Y., testable, orthogonal, and “refactorable” (at an acceptable cost). I will discuss the philosophy of design in a future post, but for now, I simply list the major pros and cons of each approach.
I review some common approaches and a few novel ones. For each, there are images, details, and an example with full source-code (See ‘Members Resources’ below).
Table of Contents
1. No Manager
This is your most basic approach. First-time Unity-developers often start with this technique. Here you put bowling ball code on the bowling ball, bowling pin code on the bowling pin, and ‘game win vs game loss’ code on something random, like the bowling ball too.
Because Unity’s ‘component-based’ approach is so intrinsically awesome (reusable code ‘components’ sit on 1 or more GameObject ‘entities’) you can indeed get very far using this approach. If you are coming from a hierarchical approach to gaming, learning the component-approach can be a challenge and your first projects may be of this ‘No Manager’ approach here in #1 or soon evolve to the ‘EmptyGO’ approach we see below in #2.
Diagram
Hierarchy
Type: Component-based
Pros:
- There are MANY free, useful tutorials created using this “No Manager” approach. So its easier to learn the basics of Unity this way.
- Flexibility for prototyping
- Intuitive for beginners, e.g. “Bowling-pin code goes on the bowling-pin”
Cons:
- It is the very definition of spaghetti code
- Very low scalability for teams (of 3 or more)
- Very low scalability for projects of intermediate or high complexity.
2. EmptyGO
This is a slight evolution beyond #1 above. Still you put bowling ball code on the bowling ball, bowling pin code on the bowling pin, BUT you try now to put all the rest of code which has no visual representation in the world onto an invisible or ’empty’ GameObject (GO). Hence the name ‘EmptyGO’.
This technique still has alot of drawbacks, but at least we begin to see game logic more centralized (on that EmptyGO). This aids readability for newbies working on your project, or for you after you return to an older project after a long time. You don’t need to hunt around everywhere to find your core code — most sits there on the EmptyGO.
Diagram
Hierarchy
Type: Component-based
Pros:
- More readable (than #1 above)
- Good mix of flexibility for prototyping (yet not AS much spaghetti code as #1 above)
- Intuitive for beginners, e.g. “Bowling-pin code goes on the bowling-pin”
Cons:
- Less testable
- Less refactorable (since less code is likely to be properly abstracted, decoupled, and reusable when compared to 3,4,5,6 below)
- Communication and referencing between GameObjects is likely too brittle (e.g. using GameObject.Find() or inspector target references)
3. SimpleGameManager
Probably the most mature technique which is in WIDE usage within the free tutorials and sample projects you find in the community is something like my SimpleGameManager technique. Imagine the ‘EmptyGO’ from #2 above, but now its a persistent (between scenes) Singleton.
Code still exists directly the GameObjects in the world, but whenever possible it calls centralized code [e.g. ‘SimpleGameManager.Instance.playSound (“GunShot”); ] Its a good approach and an appropriate (simple) solution for many small projects.
Diagram
Hierarchy
Type: Component-based w/ Manager
Pros:
- Ultra-fast setup (but with minimal functionality). Its more of a racetrack — where YOU must supply the race-cars.
- Persists between scenes, and if its not created it will create itself as soon as it is referenced (because its a Singleton).
- Ideal for prototypes (but thus not scalable)
Cons:
- Its not plug-and-play per say. The current workflow is to import the package and EDIT the core class, rather than use/extend.
- Not D.R.Y.
- Less testable. Much of your code STILL sits around on various GameObjects (like in 1 & 2 above).
Sample Game
- Coins And Platforms (Play The Game, View Video, Download Full Source-Code)
4. uMOM
My (unreleased) uMOM Asset Store project arose from a problem inherent in Unity. There is no default Main.main() type ‘hook’ to centralize the entry into your run-time and no default way for UI and code to persist from scene to scene. This was the genesis of the Unity Manager of Managers (uMOM), pronounced as /you-mom/. You can read more at the uMOM Dev Diary and see the status of the project (it has some issues). Here is a short summary of purpose and benefits;
The uMOM package allows developers to add one or many reusable, custom manager classes to the project. Each ‘start’ automatically, have a predictable life-cycle (reset, add, update, remove), optionally receive ‘update()’ calls, optionally run during edit mode, and optionally persist between scenes. Managers operate as singletons and can easily address each other to collaborate.
Types of uMOM Managers: Really anything is possible, but here is the short list of use cases I will address first. Use some of mine or none of mine – then create your own. Most any existing manager class you have can easily be converted for compatibility here.
- uEventManager -Streamline messaging between classes. Replace the need for Unity’s clunky ‘SendMessage’ and instead dispatch strongly typed objects. (The uEventManager will also be available separately).
- Store references to audio clips (drag-n-drop) and control audio playback via C# from one place.
- GUIManager – Layout UI which optionally persists between scenes. Centralize the controls to handle clicks, etc…
- PoolManager – Optimize your run-time performance by persisting GameObject or prefab instances in RAM and displaying them as needed.
- LevelManager – Queue up levels and perform transitions (e.g. fade-in-out) between them.
- GameManager – While other managers are not project specific, this one likely is. Here you manage the core game mechanics, how the user wins and loses, store the score, etc…
- SaveManager: Takes care of saving and loading user preferences and achievements.
- MenuManager: Controls all menus, managing their animations, their contents, and their behaviors. Perhaps it heavily uses the GUIManager for layout.
- Much, much, more…
Diagram
Hierarchy
Type: Component-based w/ Manager
Note: The images and source-code for this architecture are not yet available.
Pros:
- Reuse code between projects. That is probably its greatest strength. Ultra fast to setup with mucho out-of-the-box functionality. Nice GUI!
- Have global access (also a con) to managers which are decoupled by discipline (GUIManager, LevelManager, AudioManager, etc…) each with a common interface and life-cycle.
- Scalable to large teams such as 4-10 developers (but may require more planning upfront and dedicated team members creating the managers vs. those using the managers)
Cons:
- The benefits of MVCS separation are not implicit ( but are possible ).
- More scalable to complex games than 1,2,3 above, but far less than 6 below.
- Still in alpha with bugs which prevent production-readiness.
5. uMVCS
For non-game projects, such as data-driven applications, there is a clear favorite in architectures; the Model-View-Controller-Service (MVCS or MVC). For the uninitiated, its where you separate your code into 4 areas; the data, the user interface, the core functionality, and any calls to/from backend-servers. It seems like OVERKILL at first, but once one is well-practiced he/she can drop in a template (e.g. Unity Package) and in 5 minutes be ready to rock.
The “uMVCS” is a ultra-light framework I created myself. Its one of many, many setups for MVCS. I created recently, from scratch in just few hours for ACADEMIC PURPOSES ONLY. It is not complete and scalable like other implementations, but if you have never touched MVCS before, its a great way to learn.
Type: MVCS
Note: The images and source-code for this architecture are not yet available.
Pros:
- Great for learning
- Uses a custom event-dispatcher implementation of the observer pattern for decoupled communication from any scope to any scope.
- Heavy use of Singletons (also a con) allows access to the ‘architecture’ from any coding scope.
Cons:
- Purposefully incomplete, it exists just to help newbies learn about code-separation with MVCS.
- No command-pattern.
- I created it in 90 minutes. Ha.
6. StrangeIoC
Here we add to organizational benefits of MVCS the ease-of-development feature called inversion of control (IoC). To learn more. Here is the official Strange diagram of the MVCS overview and the StrangeIoC website.
Diagram
Hierarchy
Type: MVCS w/ IoC
Pros:
- Public, Community-driven, well-documented. (e.g. You can hire/contract a new developer who arrives with this skill on day 1)
- More decoupled, testable, & D.R.Y.
- Scales-up well for large teams, large projects
Cons:
- Slower to setup (but faster to add last-minute changes)
- Steeper learning curve, especially for junior developers
- Demands discipline/know-how from your team to put logic in its proper place (but removes the ‘where should we put that code?’ decision process)
Sample Game
- Spider Strike 3D (Play The Game, View Video, Download Full Source-Code)
- Paddle Soccer 2D (Play The Game, View Video, Download Full Source-Code)
What’s next?
Want to learn something more basic? Or are you ready for more advanced topics about UnityEngine and C#?
Checkout SamuelAsherRivello.com/learning/!
Downloadable Resources
- Download Bowling Game source-code (1. No Manager )
- Download Bowling Game source-code (2. EmptyGO )
- Download Bowling Game source-code (3. SimpleGameManager )
- Download Bowling Game source-code (6. StrangeIoC )
What are your thoughts?
Do you prefer an alternative to the suggestions above? Or do you have an additional recommendation?
Let me know! Twitter.com/srivello