#How do you design a game system?

1 messages · Page 1 of 1 (latest)

woven adder
#

I started 2 years ago with Unity and C# and would consider myself an intermediate programmer. I'm also self taught. I'm working on a game with 5 other people and I'm responsible for the whole gameplay code. Basically everything except UI. Now my latest system I had to program was an event driven announcer and one-liner system. So basically anything that happens ingame could cause an event and I need to catch it and play audio tracks. Sounded pretty simple to me at first. But once I got into it I realized this would be really difficult. First of all there are so many different events and I have to keep it performant. Then I want the system to be open closed. I want to be able to add AudioEvents just by creating a ScriptableObject and setting up a few parameters.

I now sometimes try to design code with visual-paradigm.com because I want to try to design better from the start and avoid having to redesign systems after noticing they won't work as expected at some part. Also it's super hard to keep the whole design in my head and check for edge cases without having it written down. Now I tried this visual-paradigm approach with the Audio Event system an quickly noticed it didn't help me at all and I had no idea what I was supposed to do. So do you have any tips or resources I could use to learn the design process?

For those interested I ended up with a static generic EventBus<T> so events can be published and subscribed to from anywhere. I subscribe with AudioEvent<T> SOs that subscribe with their T event type and check some Conditions<T> before notifying an AudioEventHandler that they want to be played. This Handler then decides over priority and so forth. I hate that I had to make everything strongly typed. I tried a more generic version before but I ended up with Conditions that had to get their own context from the game, which was weird and error prone. Now my Conditions get the context directly from the event, but I need to do a bit more maintenance (more classes)

fringe gate
# woven adder I started 2 years ago with Unity and C# and would consider myself an intermediat...

when you are responsible for 'everything' you main goal changes from "making it work" to "making everything work together forever". And its a complex story how to get there, much of it depends on the team workflow and the actual people in the team (more so when the team is small). There is no golden path that works for everyone. But there are patterns that scale (over time and head-count) and those that don't. There is also a a gradient of what you need at the start and what you need towards the release. You need to figure out patterns and structures that can grow. Unfortunately these can't really be generalized for every game. And the popular patterns you hear about, like the mentioned event bus, are just generic principles you have to adapt to your actual problem space.

The best approach is to learn all the patterns, understand their tradeoffs, understand what problems they solve and when they become neccessary. If you use patterns that don't solve a specific problem for you, all you gain is extra work.

#

you can make a successful game with 3 people, sell 1M copies with the most basic patterns, but those patterns will not work with 30 people, not for multiplayer, not for live services, not for consoles or mobile, not for DLCs, not for modding. And they might even break with just 10. Conversely, the 30 people patterns will also not work for the 3 people team.

#

but if you know the 30 people pattern, you know what you need to do with 3 people that you can grow into the 30 people patterns and beyond.

woven adder
#

This is where I want to get. To design scalable and solid systems. But when it comes to deciding for the patterns that I know, I find it hard to get the whole picture of the system in my head. Do you recommend anything for that?

fringe gate
#

you cannot make a system that scales from 1 to 100 without change

#

you need to understand how to design it so you can incrementally replace parts of it that you have outgrown

#

this means you can just start anywhere by solving the problem you have (today) in the most direct way possible.

#

from that you learn what works and what doesn't, provided you also read a lot about theory. if you don't acquire theory and think about stuff, you will get stuck (as an organization) with tons of path-dependent tech dept and bad processes.

#

the only way around getting stuck is building everything in a way that it can be replaced easily. and thats much easier said than done.

#

I would recommend you start by reading "A Philosophy of Software Design" by John Ousterhout

#

TLDR: basically all named patterns are anti-pattens in most situations for most people.

woven adder
#

I think a lot about things like scalability, usability, performance... And then I tend to get stuck in my head where I find it hard to decide which is the most important and what is a good tradeoff. I've never really read anything about software design (except for Unitys SOLID Ebook). I learned about most patterns by chance. I will look into what you recommend. Thank you.

fringe gate
woven adder
#

Performance is usually easy to do, but it requires tradeoffs. At critical places even avoiding a dictionary call or method call can improve it. But usually it's more about understanding the GC and when to calculate things and when not to (every frame). Scalability comes from abstraction and modularity I would say. But I feel like abstraction can lead to a lot of overhead and can be hard to maintain (many classes). And modularity is something I tried with the NPCs for example, but it lead to quite a few classes and I'm not sure I like it. I tried to use more composition in this project. With Usability I mean how the Designer can work with the system. Sometimes it's more important and sometimes less. But also how other programmers or myself can use the system and how stable it is (so not easy to cause errors).

fringe gate
# woven adder Performance is usually easy to do, but it requires tradeoffs. At critical places...

i would say you're on the right track regarding abstraction and usability, but you should treat performance more as a design and structural problem. algorithms and datastructures are important, but they can't help you if you've designed an unoptimizable structure. its generally a good idea to loosely aim for processing everything in batches with high cohesion. that leads to optimizable systems.

woven adder
#

I see. I will into that. Thanks again!

fringe gate
#

also, make sure you profile your stuff before you chase peformance phantoms and mirages or worse: follow some random generic advice on the internet 😛

woven adder
#

haha thanks