What Went Wrong
Overly ambitious design.
In retrospect, we were in some ways our own worst enemy. Many of the team members had wanted for some time to do a really huge, ambitious role-playing game. When we actually started the project and had a budget and schedule, we probably weren't realistic about how long RPGs typically take to develop, especially one that travels to four different cities across an 800-year timeframe. We were very reluctant to make big cuts in the design, such as cutting one of the two time periods or removing the multiplayer aspect. Because of this, we eventually had to make the decision to miss our first scheduled release date of March 2000. We also cut back on our plans to release an interactive demo some months before the game and scaled back the scope of the multiplayer beta.
Fortunately, by expanding the schedule a few months (from March to June), we were able to preserve almost all the elements from the initial design. But to accomplish this, the art and design departments really had to work above and beyond the call of duty for an extended period of time.
We did cut back a bit in the area of multiplayer by removing the ability to play through the entire single-player scenario cooperatively as a team, and instead replaced that with two smaller, custom-made multiplayer scenarios using levels and art from the single-player game. Part of this was because we did not plan properly for multiplayer when making some of the Java scripts that drive the single-player game. If the multiplayer game had been functional earlier in the schedule, the single-player game scripts might have been written from the start to be "multiplayer friendly" and we could have shipped more multiplayer content in the box.
Characters were created with a budget of between 1,000 and 3,000 triangles. Boss characters, such as Ahzra the Tzimisce Elder were generally the most complex.
Prototyping with a proprietary API.
When we started developing the 3D engine for the game, which we named Nod, the 3D API landscape was quite a bit different from how it is now. We decided to use Glide as an initial prototyping API with the belief that it would be a more stable platform and avoid the complexities of supporting multiple hardware through a more general API until we had solidified the engine a bit. However, once we had a basic, functional engine running under Glide, the programmers' attentions turned toward game play and functionality rather than switching the graphics engine to a more general API such as Direct3D or OpenGL.
Because of this "if it ain't broke" mindset, we expanded our support beyond Glide fairly late in development. At the first public showing of the game at E3 in 1999, we were still basically a Glide-only game, which meant we couldn't demonstrate the game in 32-bit modes or support some features not present in Glide at the time.
The extensive use of Glide also gave us some unrealistic performance estimates for other hardware. Since Glide allows low-level access to things like texture-memory management, we spent significant time writing our own optimized texture manager. When we switched to Direct3D, most of this work had to be discarded. Since Glide allows more flexible vertex formats than Direct3D, some of our underlying data structures needed to be changed, which meant re-exporting hundreds of levels and models. We were making low-level architectural engine changes at a stage when the engine should have been pretty much locked down. Also, because we switched late in our development schedule, we probably didn't spend as much time as we should have on compatibility testing with a wide variety of hardware. In retrospect, we should have switched to Direct3D or OpenGL several months earlier in the development schedule.
One problem we identified early in the development process was the problem of pathfinding. Navigation of variably-sized characters through a completely free-form 3D environment is one of the most difficult problems I've had to tackle as a game programmer. Unit navigation is hard enough when you have a flat 2D plane or restricted 3D environment, but in an environment where the level designers are free to make stairs, ramps, or any other 3D construct you can imagine, the problem becomes exponentially more difficult. My natural tendency when presented with such a sticky problem is, unfortunately, to make it good enough for the early milestone and demo builds, and then just "deal with it later." Unfortunately, "later" quickly became "now," and "now" turned into "yesterday."
Real-time continuous level of detail allowed models to appear highly detailed in close-ups without sacrificing speed in longer shots.
We should have tackled this problem much earlier, before the levels were near completion. We should have worked with the level designers to come up with a set of restrictions for their levels, or some additional tagging in the editor to specify to the engine where characters should and should not move. Instead, the only hints from the level-design tool were "walkable" floor flags, but little or no special marking of walls, cliffs, and other pathing hazards. Since we waited too long to address the problem, better solutions such as walk boxes or walk zones would have taken too long to retrofit into the more than 100 levels already in the can. Instead, we spent weeks making small iterative fixes to the system to hide the most extreme errors and turn what was an "A" bug into a "B" or "C" level problem.
Feature and data timing.
This is a fairly common problem in games I've worked on, and Vampire was no different. The technology team typically looks at the development schedule and schedules that entire block of time to achieve a certain feature set. Often, however, new engine features get added too late in the schedule to be utilized fully by the designers and artists. This happened several times during Vampire. Some of the more interesting special effects, for example, were added only a few weeks before the data was to be locked down for final testing. Other features that we added couldn't even be implemented extensively. For example, we added a more flexible shader language so late that only one to two percent of the surfaces in the game were able to take advantage of it. Some features that we had originally planned for the engine, like bump mapping and specular lighting, were cut completely from the initial release because there was insufficient time both to complete the feature and to create art to drive it. We softened the blow somewhat by moving some of these features to a planned patch, which would add them later if the game proved successful.
Unfortunately, there are very few programming tasks that don't require some sort of artist or designer input to find their way into the finished product, so unless programmers spend the last six months of the project doing nothing but fixing bugs, some of this is inevitable. We can justify it to a degree by looking toward the likely sequel or add-on projects as a way to take advantage of some of the engine work that was underutilized in the original title.
As the project was drawing to a close, we found that we ended up with a bit "too much game," as someone put it. From the start, we decided to author our data for a high-end platform, so we'd have a good-looking game at the end of the 24-month schedule, and also because it's much easier to scale art down than up. Unfortunately, we never really started to rein in our art and design teams when we should have near the middle of the project. Instead, we continued to add more and more resources to the project, resulting in a minimum installation footprint of about 1GB.
We authored all our textures in 32-bit color and then scaled them down at load time for 16-bit cards. Our models were also extremely detailed (1,000 to 2,000 triangles each, on average) and relied on automatic level-of-detail algorithms to scale them down for slower machines. We lit our levels with relatively high light-map resolutions. All of this made the game look great on high-end systems, but it meant the game was fairly taxing on low- to mid-range systems. In the end, the game just barely fit on two CD-ROMs.
The game's story unfolds mainly via in-game cutscenes. The excellent models allowed for the creation of intricate details such as individual fingers, which helped make these scenes feel like pre-rendered cinematics.
We had originally planned to include both 16-bit and 32-bit versions of the game textures and allow players to choose which version to install, but after all the art was completed there was no room on the CD for more than one version. Likewise for sounds: we wanted to include multiple quality levels but space prevented this. We actually compressed most of the voice samples with MP3 and had to remove several sounds from the game in order to fit it on two CDs.
In the end, our game looked gorgeous but had difficulty running on machines with less than 128MB of RAM -- and even then, it used a fair amount of space on a swap drive. This glut of resources will also make it more difficult if we choose to port the game to a more limited console environment.
At Last, Redemption
For the first project from a new development startup, I can't imagine how things could have gone much better than they did, except perhaps if we could have avoided shipping it the same year as Diablo 2. As a company, we managed to accomplish the three most important things in this business: not running out of money, not losing any team members, and actually shipping the product. Our publishers remained committed to the project throughout its life cycle, and even increased their support as the project continued to take shape.
The course of development was amazingly smooth, with very few surprises or conflicts along the way. In this industry, you can almost bet that at some point in a two-year development cycle, something traumatic will happen to either the development team or its publisher, but for us the waters were remarkably calm. About the most exciting thing to happen during development was when we lost our entire RAID server while attempting to add drivers to it, resulting in the loss of a few months' worth of archived e-mails.
Our good fortune allowed the team to focus strictly on the game and prevented distractions from outside the company. Also, keeping our company focused on just one title and resisting the frequent temptation to take on more work and more staff allowed everyone to be on the same team with little or no secondary distractions.
Hopefully, by avoiding feature creep and a four-year "death march" kind of ending to this saga, we can avoid a lot of the burnout that we have seen and often experienced on other teams. By maintaining links with both the fan community through our web board, and with the developer community at large by attending shows like GDC, E3, and Siggraph, our team was able to keep a positive attitude and high energy level throughout the schedule. We remain convinced that small development teams with a single-title focus are the best way to ship quality titles consistently, so our plans moving forward are to staff up gradually from 12 to perhaps 16 people over the next few months and embark on our next two-year ordeal a little older, a little wiser, and just a tiny bit larger.
|Full Time developers||12|
|Length of development||24 months|
|Release date||June 2000|
|Hardware used||Intel and AMD PCs, Nvidia and 3dfx 3D accelerators|
|Software used||Alias|Wavefront Maya, Photoshop, QERadiant, Visual C++|
|Technologies||3D skinned characters,
continuous level-of-detail, custom-built 3D engine, MP3 audio compression,
Lines of code: 300,000 for game, 66,000 lines of Java for scripts.
|Lines of code||300,000 for game, 66,000 lines of Java for scripts.|
Robert Huebner is a co-founder and lead programmer at Nihilistic Software, an independent game developer located in Marin County, Calif. Prior to working on Vampire: The Masquerade, he contributed to several other game projects, including Jedi Knight: Dark Forces 2, Descent, and Starcraft. Robert is on the advisory board for the Game Developers Conference and has presented a number of sessions there, as well as at Siggraph and E3.