SakeTami
TheGatewayOfRealities
TheGatewayOfRealities

patreon


Dev-blog 2.0 - Content System

 

Hello, it’s Hopfel again!

It’s been a while since my last post, but we’ve been steadily working on exciting new features we’ll be able to show you soon. For now I will go over one of our core implementations, the content system.

Similar to RPG games, we have to deal with a lot of different content types, prominent examples being items, weapons and actions(skills) but also less obvious ones like animation modules, movement modes and body parts.

All of these content types have the following properties in common:

A good case-study for this is Minecraft Forge, a framework that not only handles loading and maintaining different Minecraft mod packages, but also provides an interface for mods to try to prevent conflicting content and maintain proper versioning.

The Content Tree

Content is organised in a tree structure. Take for example the walking animations for different species: a quadruped dragon has a very different walking cycle than a bipedal lizard character, but we don’t want to reimplement the whole animation pipeline for every species (this is one of the reasons many games like Skyrim share skeletons and animations between characters, even if they are of different species).

This creates a natural content hierarchy: “quadruped walking animation” and “bipedal walking animation” both are a “walking animation”, which is an “animation” which is a “content”.

 

For programmers: The content hierarchy is a separately stored sub-graph of the class hierarchy.

To then allow relations between content types, all content classes have a list where they reference other content classes: the insertion list.

For example, the species content type “Hizathri” contains the insertion “Bipedal walking animation”. So when the movement system wants to play a walking animation, instead of directly specifying what animation to play, we request it to grab the first walking animation it finds in the insertion list of its species.

Insertions are have a one-to-many relationship: Content types can once be inserted into many other content types.

These insertion lists are open to modding. A modder can easily swap the walking animation for a specific species, or add a new head model for their customisation by adding new content to their insertion list, all without any additional programming required.

Serialisation for networking

Content type references need to be sent via network, for example so the server can tell all players which items they have in their inventory. For that, it is important that content types can be sent using as little bandwidth as possible.

Content types are indexed when the game starts, as sending a number uses significantly less bandwidth than sending e.g. a string for the content name. This index is assigned by a content type’s location in the content tree.

Ingame screenshot of our developer tool. Note that not all content types have a number. Content types like “Animation” are abstract, they aren’t used anywhere but for categorisation.

Bandwidth can be reduced even more when it is already known which content type is expected. You only need to send the relative offset to the expected type. In the tree pictured above, for the "Walking" animation instead of index 25 (which uses log2(30)=5 bits) we can send its relative offset to animations of 5 (which uses log2(6)=3 bits)

Following some examples of the content system in action.

Example #1: Dimensions

Our game consists of multiple big and small levels we call Dimensions. Small dimensions we call “Mini Dimensions”, which are mostly self-contained rooms or dungeons that can be entered through doors. Mini dimensions are created and destroyed in a dedicated space in the world a few kilometres below the main level. Big dimensions we call “Realities”, which are the big instances you load and enter through the Gateway. Unlike mini dimensions, there can only be one reality loaded at once.

The Crossroads Reality (top) gives access to multiple mini dimensions bar, dorm, baths and restrooms (bottom).

Concurrently active levels have to be loaded in the same euclidean space, as the Unreal Engine does not directly support seamless instancing (yet).

Dimensions can have loader content in their insertion list. These loaders are responsible for level modifications, such as different weather or placing/removing certain NPCs and other objects. This allows us to define reality modifiers to let players customise Realities and adjust difficulty (akin to Mutators from Unreal Tournament games). It also enables mods to add or remove objects in already existing dimensions.

Example #2: Character Customisation

We put a big emphasis on an as diverse character customisation system as possible. Every character is made out of body parts that can be swapped and customised individually. This customisation can include colouring, material changes (e.g. glow, metallic) and mesh morphing (e.g. belly size).

Body parts are organised in another hierarchy: the torso has a head and spikes, the head has horns, and the horns can have piercings. The insertion list of a body part contains all attachable body parts and supported customisations. 

Customisation changes propagate down the bodypart hierarchy. Changing the primary colour of the torso will also change the primary colour of the head (if not already customised).

Example #3: Knowledge tree and trackers

In our knowledge tree every node is a content class, each uses its insertion list to define…

Trackers are content types that track statistics about the player in the form of a number associated to a context. A context is a list of content classes that are in any way interacting with the player at a given time:

Distance Tracker: Bipedal Walking - Hizathri - Testmap = 64
Translates into:
<Walked> for <64> metres as a <Hizathri> in the <Testmap> level
These trackers can then be queried using a filter:
What <Distance> has the player walked as a <Hizathri>
Which would add up all distance trackers that contain the Hizathri species in their context.

Multiple of these trackers can be used as requirements for unlocks:

While the nodes themselves are hand-made, the knowledge tree’s visual layout is automatically generated. Mods can very easily add new knowledge nodes anywhere in the tree with custom requirements, adding new challenges to the system.

Conclusion

The content system is at the core of TGOR and informed a lot of design decisions. It is surprisingly simple yet powerful, allowing not just us but also modders to add content to our game quickly, safely and with minimal coding if any.

Dev-blog 2.0 - Content System

More Creators