5 ms·
I enjoy tinkering with Unity. One thing that I am struggling with though is settling on good ideas for general architecture for structuring the logic, and then
by mattlondon 6y ago
I enjoy tinkering with Unity.
One thing that I am struggling with though is settling on good ideas for general architecture for structuring the logic, and then doing things like communicating between entities/objects in a scalable way. Not everything that needs to communicate exists in a nice parent-child relationship - occasionally you need to communicate "across branches" in a hierarchical tree when there is no other interactions such as collisions etc.
You can get a long way with just cobbling stuff together, but eventually you get into growing pains where it becomes a mess.
The "best" solution I have so far is awkward "god"/"manager" objects that act as glue to let everything access everything. There has to be a better way?
The nice with with Unity though is that the logic is in .NET IL so it is trivial to see how people are doing things and learn.
- meheleventyone 6y agoTypically games use a messaging system similar to the sort of thing you'd expect implementing the Actor model. This lets you keep things decoupled whilst still leaving them the ability to communicate. It's pretty handy but also needs to be used with care if you're not going to invest a bunch of time in writing tools to support it as it makes debugging tricky. Don't be too worried about mediators though. Games are a little bit different in that you typically want to act on a shared world. If you have systems that act globally on the world then you're just matching the data that exists. Even the physics system itself is basically a singleton that's mediating interaction.
- FroshKiller 6y agoI haven't used Unity much, but I know components are a big deal. You add components that define things like an object's collision behavior or what audio it plays, and when you need to use those components in a script, it has a service locator approach to retrieving an object's components.
- Jorge1o1 6y agoThe best way to communicate across hierarchies is to set the other GameObject/Component that you need to communicate with as a public field and then manually set that GameObject via the Editor so now the UI has a reference to the Player’s Gun’s AmmoBehaviour. You can then use Events and EventHandlers to have the UI subscribe to every shot and now it can show how much ammo is left in the gun. This can get kind of tricky if you use a lot of procedural generation or prefabs where for some reason you can’t immediately set the reference to that other GameObject (for example, the player has no gun yet). In those cases you should try to set the reference programatically, such as when the Player picks up the gun. You might have a reference from the Player to the HUD, and when the player picks up the gun you set the Gun’s UI reference via some SetUiObject(GameObject ui)
- Eyas 6y agoInstructions of a "God" game object, try a ScriptableObject! But you're right cross object communication is tough. I end up relying on asset-ized SOs to do a lot of this. When communication between any two nodes is mostly one directional, events and triggers work great. (Ryan Hipple has a great talk on this, just search for "Ryan Hipple ScriptableObject".
- andypants 6y agoI recommend dependency injection with extenject: https://github.com/svermeulen/Extenject https://github.com/svermeulen/Extenject
- Audiophilip 6y agoInstead of having your game sub-systems and components reference each other in a scene, you'd better off designing your game architecture in a data-oriented way. Try organizing your code around the data your components have to work with and let your code react to changes to that data. Using Scriptable-objects is a great way to facilitate this model, because with them your game components will reference data assets instead of other components, reducing dependencies, which gets harder and harder to manage as the complexity of your application grows. I can really recommend watching Ryan Hipple's presentation titled "Game Architecture with Scriptable Objects". [0] At our studio we've built a framework based on these ideas for a high-complexity game project and we're very happy with it so far. We have a clean and well-performing codebase that's easy to maintain and test, because no sub-system has any hard dependency on any other sub-system. [0] https://www.youtube.com/watch?v=raQ3iHhE_Kk https://www.youtube.com/watch?v=raQ3iHhE_Kk
- mattlondon 6y agoThanks (and to the other comment who suggested the same talk). This was useful. The tl;dr for anyone who can't spend an hour watching (why are so many Unity things done as videos?!?! so infuriating!) is that you use "Scriptable Objects" (new to me - this is a first-class thing in Unity) to store common state and so break statically defined dependencies between Game Objects by having them share the Scriptable Object rather than reference each other. So you might have a Scriptable Object that contains the player's score/coins picked-up/zombies killed etc. On its own this is conceptually basically just a number/several values/etc wrapped in a small singleton class. You then reference that Scriptable Object in your player game object/script that will mutate that value. Anything else that needs to know the score/coins picked-up/zombies killed (e.g. UI code) references the same Scriptable Object. So now two separate parts of the game share the state without being statically bound to each other (they are only bound to the Scriptable Object). Plug in as many or as few new components all using the same state stored in the same Scriptable Object and nothing else needs to change as they only share the Scriptable Object. No references to other game objects required. You can do the same for events - create a Scriptable Object for an event (e.g. PlayerHurt or PlayerShoot etc). Since Scriptable Objects can contain code like any other class, you can have GameObjects register their interest in this shared singleton event by calling "PlayerHurt.RegisterListener(this)" etc, and then have another GameObject trigger/raise/activate the event ScriptableObject ("PlayerHurt.Trigger()" etc). Neither side know about each other, so you can plug in as many or as few listeners as you want. The talk uses some extra cleverness to use a UnityEvent to allow for a function call in reaction to the event being triggered - this means a lot can be done directly in the unity editor, but that seems separate from the main secret-sauce of the scriptable object as the mechanism for shared state. Site here that basically repeats the video nearly verbatim: https://unity.com/how-to/architect-game-code-scriptable-objects https://unity.com/how-to/architect-game-code-scriptable-obje... Cheers!
- symlinkk 6y agoI thought that’s what tags were for.