My name is Joel Juvél and I’m the Lead Programmer at Guru Games. I like developing custom tools and solutions that can speed up development. When developing games, complexity can easily get out of hand if one is not careful.
Game development is a non-static process, it’s often impossible to know beforehand if something will be good or not, before implementing and testing. This can put a lot of stress on your team if they have inadequate tools to work with. If you have to frequently work with tools that are either to complex or inflexible, you end up trying to avoid changes, as it could increase the risk of the whole project.
I try to identify such risks before they become a reality and find a solution before they get out of hand. During the development of Magnetic I have made several custom tools to solve a wide range of problems. For Magnetic we choose to use Unity as our target game engine. No game engine is perfect and they all present different types of challenges. One key problem with Unity is the difficulty of managing gameplay complexity when scenes get big. Let’s say you have the following situation. You want to play an animation when the player walks into a trigger box. When the animation played for 2 seconds you want to play a sound. The straight forward solution would be to make some type of trigger system using components. Then you could make a system where animations trigger other events. Now let’s say you want to add some other custom logic on the fly, maybe it should only be triggered once etc. Eventually you will end up with a complicated system if you aren’t careful.
With only components and game objects it’s very hard to structure and present all types of data. Especially game logic! There are many solutions to this problem. Having evaluated other engines like Unreal & Cryengine, I was leaning towards a sort of visual programming tool; some type of flow graph system. The motivation was to dig out the game logic into plain sight instead of having it hidden in game objects and components. Another motivation was to empower our level designers with easy to use tools that would require less support from programming.
So I began with the task of creating such a system. The system doesn’t have a proper name yet though, but I’ll figure something out soon. :) It’s important to note that this system is absolutely not meant to replace regular programming. It should be view as an event system. At the core the system contains nodes that perform some type of task. Such as playing an animation, sound or maybe enabling/disabling a game object. Games are often event driven. You perform an action and get some type of reaction, such as a sound or an animation. The nodes have input and output pins connected by wires. Only pins with the same data type can be connected. Events are generated and queued in the system run time. They will then be dispatched when possible.
The result can be seen in the screenshot below, it’s from one of the levels in Magnetic. The flow graph editor is still work in progress. There’s always things that can be changed or improved.
The screenshot below is from a flow graph used in a lever prefab. When the player use the lever it will once and only once play an animation and a sound. When the animation finished playing it will generate a callback event. The callback event can for example be used in a flow graph inside a scene.
The system can divided into three parts:
- Data representation
- GUI system
- Run time system
The GUI system is built using a custom editor window in Unity. I like working with the Unity GUI system, it’s fast to work with and flexible enough to do most tasks. A great feature is that it works seamless with the rest of the engine, such as drag & drop with scene hierarchy. The only downside is the performance. The data is stored in Unity assets using ScriptableObject. One problem that arose was the inability to store references to Unity objects in scenes. Unity only support storing references to global assets such as prefabs, which is a sound design choice, but a bit frustrating in these situations. The solution was to make a reference manager object in each scene/prefab holding references to objects and identifying them with unique id’s (UIDs). I use UIDs quite extensively to identify objects all throughout the system.
To increase automation I rely heavily on C# reflection capabilities. For example runtime nodes are instanced and configured automatically (in most cases). A runtime node or pin is usually a mirror of their respective data representation. With reflection it’s possible to instance the nodes and pins at runtime based on their variable names and types. As long as one employ robust error handling all of this works quite well. I wanted the process of creating new nodes and pins to be as painless as possible, hence as much automation as possible is preferred. The system turned out to be quite extensible and it’s easy to create new pins and nodes. We’re probably going to release this tool on the Unity asset store when it’s closer to a finished state.
Always remember that as a programmer you have the power to supply your team with useful tools that can make all of your jobs a lot easier!
Each week we will continue to update you with another entry in the development blog, with a focus on different aspects of developing games each week. This one has been about developing tools, but who knows what we will talking about next? Maybe we’ll dive into animation or graphics? Maybe we’ll talk about the office, or the story arch for Magnetic. If you have any suggestions feel free to lets u know in the comments section below, or on facebook, twitter or Google+.