Visually Scripted Content

Data & Flow

“Quest“ (Creative, I know) is the system I’ve built to drive the majority of the content in Sons of Ryke. It acts as both a data structure & event system to drive content that has a logical flow or is time-dependent. It also handles saving & loading the state of any active or completed content.

The system is made up of a “Questline” asset that houses a hierarchy of “Events“. These events show up as nodes & can quickly & easily be added, rearranged & reordered through the grid interface. These nodes are themselves scriptable-objects, so can easily be selected & edited like you would any other Unity Object.

Questlines can be activated from other scripts or other questlines depending on your needs. Once a questline is activated it’ll start by evaluating the top-most root event. On completion, that event will pick a child event & evaluate it. This process continues until the final child in the current branch has been completed.

 

Use Cases & Potential

I’m currently using this system for tutorials, races, world events & small quests, but it’s infinitely extendable. If you need new functionality you just add new node types. Once you’ve written that logic once you can re-use as much as you like. Already I can save/load the game, reward or punish the player with currency or reputation, display UI prompts or have characters ask questions, play or intensify music & even spawn enemies around a settlement.

Events are split into 2 primary types, global & local.

Global Events

Global events execute code themselves, but cannot access anything within the scene to do so. This is useful for delays, saving & loading, scene switching, UI prompts, etc. These are the simplest types of events to write & usually access systems built on a shared data structure or dependency-injection / singleton design patterns.

Local Events

Local events locate & execute code within the scene using an identifier. This is built on dependency injection, in which logic within the scene registers with the quest system when it’s loaded/initialized & deregisters on disable or destruction.

When a local event is evaluated it searches through all registered/injected logic until it finds the correct identifier. That registered script is then initialized & responsible for completing the event once it’s done whatever it needs to do.

As an example, let’s take a beacon for a race. This would register when it’s loaded based on an identifier. For the sake of this example, let’s say it’s the first beacon in the race so its identifier is “Beacon 1“. When a questline evaluates a local event with the identifier “Beacon 1“ this beacon is initialized & lights up showing the player where to go. When the player enters the beacon’s trigger the beacon calls complete & the questline proceeds to evaluate the next event.

 

Extended Functionality

Live Debugging

Complex event chains can be prone to error. If any event/node in the hierarchy fails the entire hierarchy can stall or sit idle. Luckily the node interface presents a live feed of the questlines execution. If a questline stalls or fails you can simply bring up its editor interface & it’ll show you exactly where it’s stuck.

Save / Load

The quest system can automatically save & load the state of all questlines. Questlines can also be set as repeatable or be ignored by the save system entirely, depending on your needs. The “Ship Select“ questline, for example, is set to trigger whenever the game loads or restarts, allowing the player to select from one of their ships.

All the Trimmings

Box select, copy, paste, duplicate, undo & redo. All the standard interactions you expect are included. Unity’s editor API makes this a breeze to implement.

Previous
Previous

Meaningful GPU Instanced Rendering