Game Engine Architecture, Separation of Application, Game Logic,& GameView, to use or not to use EventManager?

Started by
10 comments, last by L. Spiro 11 years, 7 months ago
I'd say, simply use direct function calls instead of events whenever it leads to a cleaner design; define interfaces (for things like Controllable, Damageable) or use a component system so that the various aspects of the game objects stay both manageable, and directly accessible. Be less afraid of some coupling, and more afraid of possibly totally unspecified control flow :)

At my workplace I've participated in two major Unity projects; in the first Unity's SendMessage facility (which allows arbitrary receiving objects to execute a named function) was extensively used, with the idea that it would be easy to add more responses to internal events when need arises, while keeping coupling low. It quickly became a mess. In the later, SendMessage is practically forbidden, function calls are favored, but C# delegates are also judiciously used. As a result, the execution flow is much better defined.
Advertisement

As for the AI system, I think I may have misrepresented it, While a human would pull the right trigger to fire, that could have also been done by mashing the "A" button, or the left trigger, or whatever key the "Fire" Command is mapped to. The system I am proposing has a Series of commands that a player can do, such as "Fire" "Jump" "Move Forward" "Turn Left/Right" "Strafe Left/Right", and each of these commands would be mapped to the specified controls that a player could press. The AI does not send its input in as a press of the "A" button, it sends its input in as a command, for example, "Turn Left" "Move Forward" "Fire". The Human Player's input is mapped/converted to the commands.

You didn’t misrepresent anything; I was talking about exactly this system. It’s obvious that you weren’t talking about how the hardware maps to the commands that make players move. You were talking about the commands themselves, and everything I said was in regards to this concept. So, knowing that we were on the same page, read my comment again.




I appreciate what you are saying here, but at the same time, you don't offer any alternatives. Games are a complex web of events no matter how you cut it. You can't ever make a game, especially a big one, with perfectly clean logic that will be obvious when you pick it up again in a year. In fact, I don't think you can write ANY program without sometimes forgetting why you did something you coded a year ago. You just have to write good comments, and document your event system so that if you or a new person are looking at it later, you know what's going on.

I will say though, if you have an alternative to an event-based game engine, I would love to hear it because it could only serve to make me a better programmer.

Yes, they are complex webs, which is why it is a disservice to yourself to go heavily message- or event- based.
A few years ago I made a AAA game for Activision called Bakugan. It was made on an engine I had created from scratch over a 4-year period.
The engine was designed to separate parts of the game into “states” where each state was a single class that inherited from CStateBase. The main menu would be a state, the options menu was one, the character-select was one, the main gameplay area was one, etc.

Each state contained the logic necessary for that part of the game inside the Tick() function and the drawing necessary for that part of the game inside the Draw() function of that state (virtual functions).


Several years later, I have no doubts that I could jump right back into that code and start adding new features easily.
Why?
Because:
#1: Each part of the game is a little island, in its own little context. When looking at the code for any given state, I don’t need to have any global context about the rest of the game. The code inside CMainMenuState is the only code in the entire game that is related to the main menu. Whereas with message- and event- based systems, there is no such thing as messages or events that belong only to one part of the game. Maybe only some of them are used in the main menu, but you don’t have a clear indication as to which ones those are, you don’t have any feel for context, and in order to be confident about anything you are doing, you have to first gain global understanding of all the events and messages, which is non-trivial. After several years, you are going to forget which message/event has what number attached to it.
#2: In the Yoshi example I mentioned the idea is to assign a number, then register and forget. If the engine’s policy is to forget, then does that sound like something that you can resume after a few years?
When I come back to Bakugan, I can just look at the code and remember what the idea was.
But when it is all just about numbers, that is a lot easier to forget and a lot harder to remember. Especially after several projects with a whole new set of numbers have been done this way.
#3: With my system, each person on the team is working on a secluded section of the game—his or her own class. They don’t bother other people, there is no chance of one person’s work causing problems for another, etc.
But with events, messages, and tasks, you are almost asking for people to trip over each other. People will register new events with an ID that causes problems for someone else, etc. The whole team has to be on exactly the same page at all times, and if you have any professional experience at all you will know that is simply not possible.


It is a lot easier to dive right back in when you know exactly where to look for all the code that runs the logic of a section of the game.
If the engine promotes a “register it and forget about it” design, then it is probably pretty easy to forget, and a lot harder to remember.

After shipping numerous titles with this design, I have continued to use it to this day on my own engine currently in development.
If you want an alternative, here it is.




I was thinking the entire left side is all part of the game logic. The "Game Logic" box is more of a control to keep everything flowing in order. It just runs the game simulation and all the changes. The right side of the diagram can not change the game directly, it can only send commands. The game logic is where everything changes.

This is where you are going to find yourself on the wrong side of my advice.
The idea of “sending commands” could vary between people, but here I get the feeling you are talking about not moving a player, but instead sending an event through a manager that will at some unspecified point in time end up moving the player.
This is exactly what I mean by “taking it too far”. Event-based systems have a practical purpose, but this is not it. You are doomed to event-spaghetti and your code will burn in event hell if you do this.
If, on the other hand, you define “sending commands” as, “From the right side of the diagram, I can call a MovePlayer() function which commands the player to move, immediately at the time of calling,” then yes, you are on the right track.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

This topic is closed to new replies.

Advertisement