Destineer Studios developed their own technology and editor for Six Days in Fallujah. The editor (DTech) was roughly based on Epic’s Unreal Editor. When I arrived, the in-house editor looked really basic — despite having several features active below the surface.
The program had several other names such as Descartes as well as the sublime Content Editor. I’m not sure it ever had a catchy final name, though.
Having already been neck-deep in what makes Unreal good (and bad) while working on Turok, I drafted solutions to make DTech become more than just an Unreal Editor clone. This was the first time I worked with its tools programmer, Ross Tredinnick. He helped the editor make significant leaps forward in the following year.
When you come across “Flowgraph” in the notes below, it was Destineer’s answer for Unreal’s Kismet called Cognito. I worked with another programmer, Johnstone Baumgartner, to give Cognito the facelift and functionality it needed.
Six Days in Fallujah proved to be too controversial at the time, lost its funding, and laid off its team. The experience gained wasn’t lost, however. Ross and I took the proven concepts and applied them to Human Head’s Radiant Editor a year later.
Skip to the bottom to see two workflow examples (gallery slideshow or an Outliner video tutorial).
This document describes requirements and proposals for improving the game content authoring tools and production workflow. The goal is to improve quality and increase productivity by reducing the effort to create content for our products. This is not a discussion about technology “horse-power” – it’s about clean interface design, transparent functionality, and ease of use. The focus is from the end-user’s point of view.
Better tools don’t automatically create better products, but they do increase the ability to. The corollary is also true: substandard tools don’t automatically create lesser products, but they do increase the likelihood. We can’t afford to build an Indy500 car that steers with Harley handlebars and has doorknobs to exit it.
Let’s make making games fun again!
The Product Owner / Customer
The users are not engineers. They’re designers, who determine the elusive ‘fun factor’. They’re artists, who determine the look. With JSS, they’re also training instructors, who might not understand game methodologies.
Our current editor has a good framework. While we’re mirroring the successes of Epic’s Unreal, let’s take into account their shortcomings and develop beyond them.
Features to include and improve upon:
- Window snapping
- Pop-Out Tabbed Windows for single monitor users
- Locator (moveable Global axis option added to World and Local)
- Match Target (to overcome Unreal 3’s multi-select assignment shortcomings)
- Filters (preset and custom user-created)
- Property entries have user-order, not vanilla alpha-order
- All level content has unique names (for logic calling and asset management)
- Instance names default to template_## (template_01, template_02, etc.)
- Rename the “Resource Hierarchy” to the “Outliner”
- Improve the Outliner (incorporate Layers and Workspace shortcuts)
- Prefabs = a level (a simple solution for unlimited packaging and controlling content)
- Prefabs allow multi-user work on one level (sound, lighting, etc.)
- Prefabs can be imported into its global position or placed locally
- Scale tool needed (for vegetation, pictures, posters, crates, game object visibility and variety)
- Scale Lattice option to snap an object’s shape to the grid (bypassing the free-form gizmo)
- Include options to mimic SketchUp’s usability (Shortcuts and Object manipulation)
- Expose icon slots for GUI work (if no icon exists, then a text icon)
- Create an in-game Flowgraph object (a Flowgraph sequence window associated to in-game location)
- Flowgraph window organization
- Worksheet (XLS spreadsheet) option
- Worksheet window organization
Quad view without Tabbed sidebar
Fullscreen with Tabbed sidebar
Toolkit Toolbar and ToolTab
(Locator, Toggle states, Position, Rotation, Scale, Acceleration)
Manipulating objects are limited to two fixed locations: the global world axis or the selection’s local axis. One has to swap between these to frequently rotate objects accordingly.
Another limitation to object manipulation is creating them. Editors typically have one or two options for adding objects to the game world.
- Select the Resource, then move to the World View, Right-Click over the desired location, then Select “Add here”
- Double click the Resource and have it added to the World View axis (0,0,0)
Put simply, the Locator is a moveable global world axis. Bound to a key, it moves to any location in worldspace the cursor is currently at.
What’s the benefit of this?
Locators act as insertion points. Adding objects to the game world as simple as double clicking on the Resource and having it be added to the current Locator position. No more creation at (0,0,0) and then moving it. No more multi-step right-click operations.
Locators also act as a floating rotation point. Objects can be rotated from any space within the game world. Groups of objects can be rotated around one shared point in space.
Couple these abilities with the option to snap the Locator to the Camera position, Object center, or multi-selection center, one can quickly reach into the game world and manipulate objects from a variety of techniques – not just the primitive Global or Local axis.
One of the limitations of Unreal is the inability to clone or pick properties from one object to another. It involves a rather blind method of clipboarding one selection temporarily to pluck a variable from another one, then unlocking the whole process to return to normal editing.
A Match Target would allow a user to keep the current subject visible then simply drag an eyedropper cursor to another object, applying that subject’s property to the current subject.
Any icon with a light gray background can be used as a Match Target tool.
Desk_42 has a 135’ Rotation. Chair_18 needs to match that rotation. With Chair_18 selected, mouse click-and-hold the Y-Rotation icon (refer to Transformer Bar above). The cursor changes to an eyedropper. Drag the cursor over to Desk_42 in the World View. Now release your mouse button. Chair_18 has now matched Desk_42’s Y-Rotation property.
A series of houses are scattered throughout a game neighborhood. The first house is lined correctly to the North-South street. Select all the remaining houses and click-and-hold the X-Position icon. Now drag the eyedropper to the first house and release. All houses are now lined along the North-South street.
Object Classes to be used throughout the game are found in this window. Filters can be used to help you hide unwanted classes. The Find field is used to name filter items in the list.
Filters are used in the editor to hide resources from Content Lists or World Views. These range from preset filters for object classes to user-defined filters for groups of classes or sub-classes (game content).
To only show materials and models in the Resource list, select the preset “Materials, Models”.
To only show shotguns, shotgun ammo, and guard AI you can use two methods:
- Go to the Filter list and select NEW filter, then check off the items you want to show***
- In the World View, select the items you want, then right-click and “Create New Filters” (Alternatively, you can choose to remove items in view by right-clicking to “Add to Current Filter”)
***new filters could automatically include common base items, like models, terrain, and sensors.
Filters are accessed through a dropdown list of check-marked choices to show what’s currently active. Filters can be created, deleted, or edited through the Filter window (or Filter tab if project tabs are being used in the Game Editor).
Filters are .FTR files saved in the Filter directory (/Project/Game/Data/Filters/). Preset filters are stored with the Project in Perforce. User-created filters are stored on the local drive. User-created filters can be shared among users or become an official preset by adding them to Perforce.
In an effort to standardize industry terminology, the Resource Hierarchy would benefit being renamed to the more common term, the Outliner.
The Outliner is the most commonly used feature of level design (outside of perhaps Properties). It’s the tree that every item in the level hangs from – an outline of the game world. By combining various methods from other applications and fine-tuning its feature set, we’ll be spending less time managing our content and more time discovering the game.
Another popular feature found in other applications like 3ds Max and Maya is Layers. Located in a different window, Layers are used to associate objects so they can be toggled hidden without changing their individual visible states. Each Layer can be applied a color to have its contents optionally tinted. Objects can be associated to only one Layer. Layers do not display their contents (just who’s hanging out in there??)
By combining the functionality of Layers with the Outliner we create a multi-tiered content management system. Layers exist at the base, allowing any number of groups and sub-groups to be created beneath each layer. The coloring function in Layers can be used to quickly visualize gameplay areas within a level. Clicking on a Layer icon prompts a color picker window allowing its default white color to be changed.
Each item in the Outliner displays an object-class icon before its name. Each name is unique, if not by its proper name, then by an automatic numeric suffix (i.e. Car_01, Car_02, etc.) A red lock icon appears over item icons that are locked (visible but not editable). Hidden items have their name italicized and grayed out. Lock and Hidden states for each item can be toggled with their corresponding Lock and Eye icons.
Now the real power! The Outliner is actually two lists. The top lists every object in the level. Consider it the ROOT Layer. Parent / Child relationships can be created by binding a selection of objects to one other object. (i.e. all geometry associated to a door switch is childed / branched to its Interaction Class).
The bottom list has the familiar group view. This is the workspace area. Groups created here can SHARE same items amongst each other, very similar to a Microsoft Shortcut. (Maya overcomes this limitation by providing a third option: Sets.)
Items in the bottom list reference items in the ROOT Layer. If you want remove an item from the level, deleting it from the top list removes it from the game. Deleting an item from the workspace only removes its reference in that group. Any Layer or Group can have its branch set to Active. This means any item added or pasted into the game world is added to the Active branch in the Outliner (only one branch can be Active at any one time). The Outliner can be outputted to Worksheet window, which is a flat view of all contents column sorted by type (an Excel spreadsheet of data).
Let’s say you have a level that takes place in a skyscraper. It has geometry, global logic, and two unique events. How would you organize that with the current method? Probably like so:
- Group_01: All geometry
- Group_02: Global logic, all navigation meshes, skybox, objectives
- Group_03: Event 1 logic
- Group_04: Event 2 logic
How do you isolate all relevant items to the first event? You’d first select Group_03, then hand pick items from Group_01and Group_02 each time you wanted to change the event.
With our new Outliner, it’s quite easy. Simply select Group_05.
- Group_01: All geometry
- Group_02: Global logic, all navigation meshes, skybox, objectives
- Group_03: Event 1 logic
- Group_04: Event 2 logic
- Group_05: Event 1 logic, floor 18 geometry, floor 18 navigation mesh, event 1 objectives, skybox
- Group_06: Event 2 logic, floor 3-5 geometry, floor 3-5 navigation mesh, event 2 objectives, skybox
To help cross department communication and level comprehension, over a dozen prescribed Groups should be associated with each level. These will contain all items relevant to the group subject. They’ve been prefixed with numbers to provide sorting priority in the Outliner. A Home Group flag on each template sets its category. Each Home Group has a pre-defined default color scheme. This standardization can be used in user-created folders, improving the ability for all users to “read” each other’s work.
So what exactly are Prefabs? Nothing more than level files – a collection of logic, geometry or game events. Any level can be treated as a Prefab (if saved in the Prefab directory). By keeping it simple and not special case, Prefabs become an infrastructure that supports endless possibilities. Think of Prefabs as the Portal & Gravity Gun for game development: tools limited only by the imagination. Any feature that exists for a level exists for a prefab.
- A collection of models (a bench, a bus stop sign, a garbage can)
- An AI with a change (you want Guy-Type-4, but with Aggressive Behavior and dual SMGs) (no need for Unreal Archetypes!)
- A complex script sequence (if we get the in-game Flowgraph object)
- A skybox with all associated FX and animation
- A Security Door (a door model & logic, security palm switch & logic, emergency lighting & logic, surrounded by cover nodes & path nodes)
Prefabs offer two major advantages:
- Repeat occurrences only have to be created once. When the original prefab level is modified, all instances of that prefab in the project get automatically updated.
- Multiple people can work on the same level. Encapsulate portions of the level into prefabs. Each user works on their individual prefab, testing their work in the parent level.
Prefabs tap into simple level import/export functions a game editor should have. Any selection can be created as a Prefab. Any Prefab can be ‘unzipped’ into the current level, becoming unique content no longer connected to its source. At runtime, all Prefabs are ‘unzipped’. All items within the Prefab get their name prefixed to the Prefab’s name and a unique number. All logic now points to individual occurrences, removing any duplicate broadcast issues.
Like Outliner Groups, Prefabs can be nested.
Prefabs and the Interaction Class
Creating a gameplay security door can be created purely with Prefabs.
- a door model & logic (6 objects, 6 Flowgraph widgets)
- security palm switch & logic (16 objects, 18 Flowgraph widgets)
- emergency lighting & logic (4 objects, 5 Flowgraph widgets)
- surrounded by cover nodes & path nodes (5 objects)
60+ objects to debug are time-consuming! Prefabs make it easier to re-use these groups over and over, without having to reconstruct them for ever occurrence. Unique doors don’t benefit from prefabing, however.
The Interaction Class takes time management a step further by stacking the majority of interaction choices into one object. With one framework to build 95% of generic game interaction, limiting the endless ways it could be created within Flowgraphs, it’s now more easy to debug and efficient – 50% less objects to manage!
- a door model & logic (7 objects, 1 Flowgraph widget)
- security palm switch & logic (17 objects, 1 Flowgraph widgets)
- emergency lighting & logic (5 objects, 1 Flowgraph widgets)
- surrounded by cover nodes & path nodes (5 objects)
As with most Content List windows, Properties feature icons to expand or collapse subsections. The order of the sub-properties is user-defined, not alpha-sorted. Similar to Unreal, each sub-property has additional icons for options. Blue text is a field that is unique to the Instance.
Frequently used fields are showcased in the top Common category.
- Name — (a unique name, defaults to ‘template_##’)
- Template — (lets one swap templates, retaining shared data)
- Transforms — (position, rotation, and scale with Match Target tool)
- Class — (core data reference)
- Model — (its default can be overridden)
- Material — (its default(s) can be overridden)
- Visible — (is it viewable in-game?) (doesn’t affect editor visibility)
- Solid — (does it has collision in-game?)
- Moveable — (is it dynamic? or does it always stay fixed in one spot?)
- Child — This conflicts with using the Outliner to visually child.
Additional Advanced options:
- Difficulty Levels (does it exist on every difficulty level?)
- Occlude Vision (i.e. an alpha texture fence shouldn’t occlude vision)
- Occlude Camera
- Dynamic Cast
- Dynamic Receive
- Static Cast
- Static Receive
- Prefetch Priority (High, Normal, Low for streaming)
- Loaded (uncheck to not use in-game)
The Resources window lists all content within the project. Content is not grouped into packages or zip files. The Resources window is a direct link to the Project Directory content. Items can be duplicated and renamed. New folders can be created from this window (removing the need to open Explorer). In its basic form, a one item preview window displays the current selection. In its expanded form, it works similar to Unreal’s Generic Browser.
A true Terrain system can be very beneficial to rapid game development.
If we want to go in that direction, a separate document will expand upon Terrain requirements. Consider the adjacent illustration as an example of what core features should be featured in such a system.
Use Unreal’s Kismet as reference for object types and visual direction. One thing to add however is a background grid and the ability to snap widgets to the grid for quicker organization. The properties for any item selected in Flowgraphs are displayed in the common Properties window. A larger document should be created to discuss widget GUI, grid snapping, organization, etc.
The Sequence list is built into each Flowgraph window. Like any other Content List, sequences can be copy, pasted, created, expanded, and collapsed.
Sequences can be saved as external files as .SEQ files to be edited in a text editor, shared with other users, or imported into existing sequences. If LISP, LUA, PYTHON, or RUBY is used as the underlying framework for logic, then sequences would be saved with the appropriate file extension.
The most critical limitation of Flowgraphs (as with Unreal’s Kismet), is that it only references objects in the game-world. When copying game objects, the new copy does not create a new set of Flowgraph logic. Another step is required to find and duplicate logic, then manually updating all references to the new objects.
Create a new object class to be placed in the game world next to objects that use Flowgraphs. With visual representation, it becomes easy to quickly identify what areas have Flowgraph sequences. Double-clicking on the object would open the Flowgraph sequence.
If you’re a power-user and want to work quickly, you need good keyboard shortcuts. The following layout should give you an idea the number of quick commands the editor featured — without the haphazard piecemeal approach most editor feature today.
Review the simplified directory structure in the following illustrations, (with file examples in blue). The structure is an amalgamation of game production directories over the past decade. Any team member should be able to easily navigate the bulk of the project.
The Editor.exe and Game.exe are the only executables in the Project root directory. Other tool executables are found in the Editor subdirectory. The /game/data/ folder is left open to interpretation, as it constantly changes due to new technology.
To protect against lost work, the Game Editor autosaves the current level, providing 10 backups per level. The default save interval is 10 minutes, which can be throttled between 1-60 minutes.
Level files (.LVL) are located in the Levels root directory. Any files related to that level are located in a subdirectory of that name (.LIT light files, .POS position data, .SND sound files, etc.)
Testbeds is for any content intended for internal use, and not required for the released product. Artists, designers, and engineers can place items here for testing, without polluting the core Project contents.
The following video was one of several tutorials for the editor. This particular one was for the Outliner. The interface was a work-in-progress at the time it was recorded (2009), so you’ll expect some rough spots. The functionality and features however, were final for the most part.
The video’s been through a couple conversions and the audio suffers the most with occasional pops of static.