Feedback Needed: Managing Quests and Story Flow in nonlinear Games

Indie Game Conversation System

Sharing my Game Design ideas for how I manage quests and flow in my indie game, and asking for some help with a few problems!

Gameplay of Exploration Games

The game is composed of several Areas (Unity Scenes) full of items, doors, viewables and NPCs that can be talked to. The experience is non-linear, so the player can go between areas as he pleases, talk to NPCs and collect/view/use items in any order.

My Quests and Conversation System

Both my Conversations and Quests are entirely node-based, using an external Graph tool, and support various script nodes (get variable, compare, execute command, etc.). The “Quests” are composed of linear “Stages”, and each stage has “Tasks” that can be added/completed arbitrarily. It is not required to complete all tasks to complete a stage, and both Quest, Stage and Tasks have their own script nodes that manage the flow.

Here’s an example (click for bigger):

Indie Game Design: Quest System

We can see the MainStory quest starting at the WhatHappened Stage which automatially adds two blue tasks. These check if certain variables are set (GV_IFTRUE) on each frame Tick and, if the first task completes, it sends to next stage. This one adds only 1 task, but upon completing each task a new is added. Additionally, if player meets a certain character, the stage itself adds an extra task too. When the quest completes, it automatically adds a new quest

Benefits

I crafted the system with the following benefits in mind:

  • Easy to Understand – Quest and Story is all Visual
  • Self-Managing – everything is in one place, no need to hunt down where and how tasks are added or completed
  • Easy to Refactor– can easily move and re-link nodes all in one place (withut clumsy menus)
  • Flexible – can easily add new tasks, multiple conditions, etc.

Problems

However, as I keep developing, I am starting to see some big problems with this system, discussed below.

Indie Game Development Console
Spitting out errors in console only helps so much

Problem 1: Variable Pollution

The whole flow hinges on arbitrary “Game Variables” (like Char.FirstGuard.HasMetPlayer or Level.PlayerEnteredOtherRoom) that are set at runtime via other quest scripts, conversations, game events, unity game objects, or any other script really. Soon enough, you end up with ton of GameVars that can become hard to keep track of (where/when/how does this get set? what does it do?).

Potential Solution: No idea. I’m already using groupings (like Char.FirstGuard.varname) but it doesn’t really make keeping track all that much easier, especially when the same variable is used in numerous places (i.e. if a player is told something, a quest can update, a door can open, another conversation may have an extra option etc.)

Problem 2: Designer Errors

Since the variables are created on the fly, the flexibility of the system can lead to logic errors or story deadlocks on edge case scenarios that may not be easy to realize until they actually occur.

Potential Solution: One ideas is to pre-define variables (perhaps in a text file, perhaps an extra node in the Quest tree). This makes it easier to spot errors (“variably xyz is undefined!”) but it adds to the pollution problem above, and adds an extra step in the design process.

Problem 3: Game-world Interaction

In the picture above, completing the TalkToGuard tasks is supposed to unlock a door. This is a bit risky, because it hinges on the assumption the Player will be in the same Unity Scene as the given door. If not, the door wouldn’t exist (yet), so it wouldn’t be unlocked, and hooray for game breaking bugs!

Potential Solution: One idea is to never interact with world directly, but use a proxy such as setting gamevars (like “Level.FirstDoor.Unlock = TRUE”) that in-world objects then check (so the door would unlock itself). This, however, further inflates complexity with an extra cumbersome step (“quest -> door” changes to “quest -> variable -> door”) which impacts design flow and potential errors. Oh, and even MORE variables to keep track of -.-

Another idea I had was for some sort of “trigger” game objects the quests can invoke, which in turn perform a desired operation. I can keep a list of “triggers to be fired” if they dont exist in current stage, or spit an error if a trigger doesn’t exist at all. While it’s safer and doesn’t pollute GameVars, it adds an even more tedius design step…

Problem 4: Referring variables by name

When you always refer to variables by their name, typos are bound to happen. Since I am using an external graph tool to make these, there is no way to really reference Unity objects directly. And I’d rather not rewrite the whole system using the in-Unity Editor at this point.

Potential Solution: Again, pre-defining variables somewhere (even in a text-file) can be a good way of cutting down on typos. I can even have a simple verify routine that walks through all scripts and checks if any reference undefined variables. Still, it doesn’t prevent design error, merely helps diagnose it.

Quest Design in other Games

I’m trying to look at how other games implement quest systems so any feedback would be great. I toyed with the Shadowrun Returns editor, and it also uses area specific quests and variables with more strictly enforced via script templates (i.e. you an only reference variables that are created). This is much easier to manage since you only have so few of them in each area, and once you finish it, the story moves on and effectively they don’t matter anymore. In my case, tho, the quest/variable effect spans the whole world, from start to end of the game.

Neverwinter Nights Conversation Editor
And this, my dear friends, is why I use Graphs for conversations

I also remember NeverwinterNights having a cool idea of storing variables inside game objects (rather than arbitrarily) which was a good way of effectively grouping them. However, again, most of the objects in Unity don’t exist until a given Stage is Loaded. It also used conditionals in conversations to ensure variables exist. Safe. But a BITCH to create.

I need to look at more open world games and toy with their edtiors. I bet there’s a reason why many Skyrim or Oblivion quests are fairly short and simple. I don’t even want to think about story and quest managements in truly complex behamoths such as Baldurs Gate or Arcanum.

6 thoughts on “Feedback Needed: Managing Quests and Story Flow in nonlinear Games

  1. One possible idea is that you can attach a ‘quest checker’ script to an object / NPC. The script would have an list of quests IDs and the corresponding stage node(s) the obj/NPC interacts with. With this, you’ll be able to have interaction across scenes.

    Here’s a quick example on how it can work:
    Scene loads. KitchenDoor.CheckLock() runs from Start().
    KitchenDoor.CheckLock()
    {
    questchecker Foo = GetComponent();
    if (Foo.SeeIfAnyQuestsHaveUnlockedDoor(/* method goes through list of quests & nodes */))
    { UnlockDoor();}
    }

    This will depend on the quest system being able to save/load variables for each quest and the checker script having easy access to them

    1. Thanks for the response Amy! Yes I can already do that but my worry is that it adds another arbitrary GameVar that I need to keep track of, making piecing the flow and debugging harder. And it means custom coding “Checkers” for any type of interaction (unlocking/locking/opening/closing doors, spawning items, changing stats etc) :/

      I was also considering a separate quest-specific vars that would be predefined for each quests, which would make organizing/tracking them bit easier.

      Im starting to think there really isn’t a “clean” way of solving the complexity/clutter issue given my setup. Looking at some other big open world games, they too seem to rely on quest variables and conditionals in convos/objects.

  2. My first thought as I was reading problem 3 was that you need a proxy variable – until you dismiss the idea yourself. However, I still think it’s a good way to go and may lead to a reduction of complexity depending on the game logic.

    For example, if the player gets security clearance for a number of areas locked by multiple doors then it’s clearly more efficient and less error prone for each door to check a single variable rather than for each script that gives security clearance to unlock each door (some of which may not yet exist).

    1. Thanks for the post Al_B :) Yea, I was thinking of adding a “Variable” node to my quest system that can be used just like the other GameVars, but are pre-defined and thus a bit “clearer” in thier intention (like you said “PlayerGainedSecurityClearance.”)

      The only reason I am againt having the doors themselves do the check is because, when complexity grows or if new Designers jump on the team, it becoems really hard to track the flow of a quest. “OK, so the clearance is gained at this point… which doors open?” Cue having to check every single door in the game to figure that out.

      Tho I could probably add some Unity Editor functionality to help with that (i.e. “find all objects that reference variable x”)

      I’m starting to think both you and Ammy are right and that’s really the best solution to my problem without completely reworking the Quest system somehow to integrate into Unity directly.

      1. I think you’ll come across the opposite problem as well – i.e. “This door is open, what quest caused that to happen?”. I don’t think it’s right for the logic to be purely in the conversation or purely in the door and having an intermediate logic block would, to my mind, help greatly.

        Not sure if you can do this in your block diagrams but being able to take something from classic logic elements would be useful. For example, take a look at this: Door example. Here I’ve sketched an example where you can be granted low or high security access (probably from different characters) and three doors. The inputs come from conversation variables or based on the state of the doors. The outputs will be checked by the doors.

        Door1 can be opened by hacking it or by either low or high security clearance
        Door2 can be opened by low or high security clearance but requires repairing first
        Door3 can be hacked or opened with high security clearance.

        Personally I find it fairly easy to follow and it’s easy to change or swap around what happens with individual doors. Just food for thought really and it still be more hassle than you’re looking for.

Comments are closed.