Validate My Game Architecture

I’m building my first game in Unity. Unity is an “asset centric” engine, however, I prefer to build “code centric” way. Thus, in my design everything is centered around C# scripts. I have something like this:

  1. Only one static Game Object: Main Object.
  2. To this GO, all the systems are attached. I have for Ex.: Video System, Audio System, Log System, World System etc. Is this the correct way? Are there some major drawbacks to this approach?

Essentially, I think about games in terms of systems, which manipulate objects. Each system is a component, attached to the Main Object. I will then create an API for each system, which will dynamically manage all GO. Will it work well? Am I doing it right?

Hard to tell. Actually Unity is a component based system as well, and having all the main components on only one gameObject is actually best practice to make sure you organize your scene.

However Unity also bases its main functionality around gameObjects, the components you add to those etc. For example when you create an enemy and attach an AI component to it, you will surely end up with another gameObject in the scene which you can and should manipulate. That’s just how it works. You will surely get a hard time to wrap this into the other “main” object.

Also in terms of optimizations you won’t get around using different gameObjects. For example draw call batching is heavily based on object parenting, combining, material assignments and so on. Without draw call batching you will most likely end up with a performance stuck at the lower end of what’s possible.

So to me it’s not really clear what you are trying to achieve. Actually you are also saying that these APIs will manage other gameObjects. If I take it like it is written, then you will end up with a structure of main components on the main object, and other components on other objects depending on their need (see enemy example). In that case, there’s really nothing special about it and it’s actually the way to go.

As I understand, you trying to make main controllers with will manager all game.
This is right decision generally. But controllers can remain static, you don’t need to create GameObject’s for them. But if Controller should be MonoBehaviot, you can use singlethon + DontDestroyOnLoad function as well.

I plan to dynamically spawn game objects from within systems (scripts). I don’t plan to attach them to Main Object. Gotta check that controller thing.

Thx for help!

Qingu,

Yes, that is generally how you would manage a single-Scene, code-centric architecture.

The most important part is ensuring that all assets are dynamically loaded, instantiated, and destroyed efficiently and without causing severe performance dips. Beyond that, your overall architecture will probably be a mix of traditional OOP design and a little bit of Unity’s component model. I find the best rule of thumb to be “only extend MonoBehavior when necessary”. While Monobehavior is very convenient for simple tasks, it can be problematic for more complex games, particularly if instance pooling, complex inheritance, or code execution order are development concerns for your project.

Also, personally, I find it helpful to have manager classes for class types rather than game engine functions. E.g. instead of “world manager”, I have managers for static world assets (terrain), interactive assets, and entities. Likewise, external assets have managers as well, which make asynchronous loading and specific asset removal very easy.

So for example, logical entities, meshes, and textures are all controlled separately. If a logical entity is created and can’t find either the mesh or the texture it wants, it displays an in-client placeholder effect (say, a little particle system) while the asset managers sort out the file loads. When all parts are present, the final asset is built out using some custom shaders to speed up assembly work, and yield is used to spread this work out over a couple frames to keep performance steady. Then let’s say another entity is created which uses a new texture, but shares the same mesh. Now when either entity is destroyed, the logical class can be destroyed or pooled, and its texture can be destroyed, but the mesh is left alone. And so on.

It’s a nice way to work :slight_smile: Good luck!
-Adrian

Indeed, I have systems for objects to. My World System has a subsystem called Entity System, which will be implemented using Model System from Video System. It seems I’m on the right track. :slight_smile:

As for dynamic instances of Game Objects, I will have to dig deeper into Unity memory management. I mean, C# does not even have a delete keyword…

GameObject.Destroy(), and the same method for other classes are what you’re looking for (pretty much every asset class in Unity has this, since they inherit it from UnityEngine.Object). Make sure to null out references where appropriate as well to allow GC.

If you have no experience in languages like C# or Java, you should read about VM memory management before building your app.
Memory management is automatic, but you should understand when WM going to delete object.