It's not every day a studio gets to reinvent the game development wheel by setting up a brand-new technology group. Combining awareness of tomorrow's trends with the knowledge gained from game development's past, Sammy Studios chose to invest in a new technical infrastructure.
Hardware and technology are changing rapidly. Game development teams and budgets have grown to keep pace. However, our methods for creating game technology have often not kept pace. We waste millions of dollars and years of time to create games that don't meet the gameplay or visual quality bar that consumers expect.
In many cases, this situation is due to methodology that we use to create game technology. Ad hoc methods used to support a few artists or tune a simple game mechanic are not suitable for teams of 30 people or more. Also, given the growing size of programming teams, ad hoc leadership and team communication styles are no longer effective.
The most apparent effect of these problems is an increasing amount of thrashing, or wasted effort within a team. Content creators (artists and designers) are often delayed by key technology; even if they do have a working pipeline, they are delayed by long iteration time between making changes to assets and seeing them in the game. On the programming side we wind up chasing frequently changing goals and conducting death-march efforts to keep pace with schedules created from some dim, optimistic past.
These are not the best conditions for creating the games we wish to create. Such conditions leave little time for exploration of what will make the game fun. At worst, they sap the passion of the developers to make a great game.
The game development industry needs to mature. It needs to develop technologies and methods for freeing up creative and content roadblocks. It needs to keep schedules realistic and provide time for refactoring our code and updating our assumptions.
To that end, this article describes building a technology foundation for a new game development studio. It's about taking all the team members' accumulated experience and trying to get it right from the start. It's about addressing specific technical infrastructure problems that can prevent us from making the best games possible. Although it is far easier to start with a new group and blank slate, every one of these problems described can be addressed by any existing programming team. The solutions presented are based on our collective experience over our careers and may be ideal for your organization, but the goal is to present a starting point. Many of our lessons learned have come from failure as well as success.
Our goal is simply to make our development teams as productive as possible. We want to give the content creators (designers and artists) fast and intuitive control through tools which allow them to discover gameplay and resolve production problems as early as possible. We want to establish a methodology that will allow the programmers to work in an effective team environment. Our focus is to create the technology and processes that will support these goals and provide the basis for a number of development projects running in parallel. The approach we've taken is to invest heavily in a technology infrastructure from the start. This meant creating a sizable Engine and Tools Group from the beginning.
The following article describes the decisions we've made regarding technology, tools, and methodology. It's about our solutions to common problems given the opportunity to start from nothing but a commitment by Sammy Studios to invest in a technical infrastructure.
Technology is the foundation for development. We want to architect this foundation to make it both flexible for prototyping and robust for production.
Data-driven design. Game design requirements are very dynamic, and our technology needs to be designed to handle this. Game behaviors and tuning parameters must be iterated frequently to produce the best results. Game engines often do not support this approach. A common practice is to embed the behavior of the game's entities too deeply into code. As a result, a programmer will end up spending a great deal of time making small code changes and building a new version of the game for a designer. To address this, programmers might create simple text-format files for storing frequently changed parameters, but don't make the parser robust enough to handle format changes and backward compatibility.
Another problem is depending too much on object hierarchies for behavior. Anyone who has written a large object hierarchy knows that moving object behavior around the hierarchy can produce a great deal of problems in the long run. An example of this is moving AI behaviors around the hierarchy until you end up with AI behaviors in base classes or a great deal of cut-and-pasted code. Both of these solutions create a fragile code base that becomes increasingly difficult to maintain.
A data-driven design can solve these problems. The system that we created is called an Actor Component System. This system allows groups of components, or basic objects of behavior, to be aggregated together to form actors within our games. The components that make up actors are driven by XML data files which the designers or artists tune with a Maya plug-in editor. Components and actors communicate with each other through a messaging system that allows the data contained in the components to be loosely coupled.
For example, say you have a locked door. The designer may want you to change that door to have it unlock when there is a specific class of NPC in view, which would require adding an "eye" component to the door. When the eye component "sees" an NPC it recognizes, it broadcasts a message to its parent actor indicating that the door should unlock and open. The benefit of this approach is that you don't have to have all door objects contain eyes, and eyes don't have to know to what they are attached. A simple scripting system glues the logic together (for example, seeing a particular NPC would trigger a door-open action). Making this change in an object hierarchy behavior model would be more challenging.
There are problems to be aware of with a data-driven design. You can easily give the designers too much control or provide too many controls to adjust in this system. This can result in unforeseen combinations of behaviors that can generate a great deal of problems. We address this issue by having programmers combine components into Actors templates ahead of time. You don't want to create a system that attempts to remove the programmer from the design loop.
Figure 1. Three-level tool hierarchy based on iteration time, depth of data manipulation, and interface complexity.
Middleware. As a new studio, middleware was an obvious choice for us. Halfway through the current console cycle is not the best time to be creating a new technology base. Creating your own core technology requires a time-consuming process of hiring specialists in programming graphics, physics, audio, and all the rest, for all platforms. The amount of time it takes to create this core engine adds a great deal of risk to development.
We chose to leverage mature middleware wherever possible, which has accelerated our prototype development. Middleware vendors provide plug-ins and exporters for Maya or Max, allowing us to focus programmers familiar with the SDKs for these programs on extending functionality for our own use.
Middleware must be carefully evaluated. We've rejected some middleware packages after our evaluation determined we could not meet our goals with them. Middleware that does not have source code licenses adds a great deal of risk and has been a big basis for not using certain libraries. Middleware that has not been used on a published game is also a risk. Such risk might be acceptable if you were replacing some existing technology, but in our case we didn't have technology to fall back on. Also, some middleware can be suited for prototyping but not for production.
Engine design. People are often confused by our effort to develop an engine after we have chosen to use middleware. Such confusion stems from misunderstanding what a game engine really is. It's not a renderer, but rather a framework and wrapper for the various subsystems (including middleware) in the application. It unifies resource management, control, sound, networking, and gameplay with common interfaces that allow them to work well together.
Engine design is often neglected, which can lead to problems. When middleware and platform implementations are not well insulated, replacing them can create major headaches. Subsystems that are not insulated from one another can create a web of cross-dependencies that build up during development and take more and more of the programmer's time to maintain. When subsystem interfaces are created independently, it becomes anyone's guess as to how systems will all work together properly.
The solution is to architect the engine and framework as early as possible. For us this began with an agreement about the coding standards and project structure. A design phase defined the top-level design, the interfaces, and several use cases describing the top-level flow of a game using it. Our framework consists of a number of subsystems that inherit an identical interface. This interface defines each phase or operation of the subsystem from startup, reset, simulation update, rendering, and shutdown (among others). These subsystems are treated as tasks with their own priorities. This framework allows us to control the game flow at this highest level of code rather than having lower-level systems having to "know" about each other.
Insulating the higher-level code from the lower levels is important. This includes creating wrappers or defines for middleware-specific types and isolating platform specifics through common interfaces. Proper interfaces are the key to solid engine design.
Generic networking libraries. Online networking is a popular feature these days, and it's important to address it early, as it's not easy. Leaving network development to later in the project will create a lot of refactoring in your game object behavior. These objects need to be developed and tested with networking technology in place.
We created a generic network layer very early and have benefited in many ways. It allowed us to test new behaviors in the networking environment as soon as they were written and fix problems that are best solved when the code is fresh in the mind of the author. There were also a few surprising benefits as well: By allowing early network play, our designers had early insights on potential AI behavior. In addition, we have fully leveraged this technology for our tools, creating robust tools that run on the PC and work and communicate with the games running on the consoles.