Tag Archives: Programming

Designing a new “dialogue” pipeline

With each new episode of The Last Door, programmers find some “spare” time at the beggining of the cycle, while the artist are concentrated in the preproduction of the new episode (writing the script, designing the puzles, and so on). Our goal for this part of the process is to enhance our engine and our production pipeline, to fix those aspects that we found more problematic while crafting the previous episode.

This time around, one of the main objectives was to replace the tool we used to create the dialogue trees of “The Playwright”.  For this episode, we used a Unity plugin called “Dialoguer” which enabled us to have the engine ready in time. In the end,  it turned out to be a bad choice for us: it was not as robust or easy to use (specially everything related to dialogue variables was really tedious). Iterating the conversations of this episodes, in the last weeks of the development cycle was indeed painful.

So, before anything else for the new episode, we knew the dialogue tree editor in our pipeline needed to be replaced. This time around, we knew better what to look for: support for multiple node selection and support for “undo”. We took a closer look at the state of the art in the Asset Store, and finally settled for “Dialogue System” by PixelCrushers.

This awesome plugin is full of features, althouh many of them won’t be needed for our pourposes. After trying a demo version, we were convinced that it met our new requirements, particularly the editor beign really robust and easy to use, and fast to work with.

The strategy to migrate the game engine to the new dialogue pipeline was:

  1. Recreate some of the most complex dialogues tree from ‘The Playwright’ inside Dialogue System, to make sure its does support all the required features.
  2. Use the previous experience to identify customization oportunities in Dialogue System’s functionality. It’s very powerfull an generic, and we’d rather need it to be exactly and only what we need for TLD.
  3. Port the dialogue manager of our game to read dialogues from the new Dialogue System’s data model. Test dialogues made with the new plugin do run ok in the game.
  4. Replace Dialogue Manager own’s localization with our engine-wide one.
  5. Port the rest of dialogues from ‘The Playwright’ using the new and now customized editor.
  6. Remove the previous dialogue tool from our code base.
  7. Simplify Dialogue System by removing everything not explcitly needed in our game, thus making the tool simpler to use, and reducing the overall code base.

This are the features we ended up customizing in Dialogue System:

  • Clasify entries by type, with our stablished set of node types: phrase, group, group choice, variable set, variable check, & event.
  • Integration with our localization system, so you can enter/modify localized text directly from Dialogue System’s inspectors.
  • Customization of the size, color and presentation of entries depending on type. Make the dialogue more readable in the diagram.
  • Limit conections from ‘variable check’ entries to two, one for ‘condition met’, and other ‘condition not met’. Make then green and red to make them easy to discern.
  • Remove from DialogueEntry class all fields that we were no longer of use.
  • Customize the context menu to create new nodes specifying the type. Make ‘group’ types only create children of type ‘group choice’.
  • Simplify the inspector of entries, so only relevant fields are shown depending of entry type.

Conclusions:

First and most importantly, we’d like to recommend Dialogue System to anyone looking for a dialogue and quest editor plugin. It’s simply great, and has plenty of features ready to be used. Additionally, full source code it’s included, so you can customize it to your needs. I’d like to add a very personal note to this: the code is remarkably well written, at least to my standards. It was really easy to undertake customizations even as deep and heavy as the ones we did.

This post describe the work of a whole week for me. The result has been not only a remarkable improvement in the time required to make new dialogues, but also in how easy and affordable is to make iterations in dialogues to improve the gameplay once we’re in playtesting and beta stages. This is specially important for The Last Door, since we really need to make plenty of adjustments iterating the gameplay, looking for the perfect look and feel for the episode.

cheers!

 

Designing a dialog system for Chapter Two

Hi everybody! It’s again my turn to talk about the development of “The Last Door”. As you may remember from my last post (viewtopic.php?f=3&t=27) I am Daniel, one of the TLD programmers so guess what: Programming will be the subject throughout all my posts!!! 😉

Today I will talk about one of the new features displayed in chapter 2 and, from my point of view, one of the most important ones: the dialog system. Following my usual writing structure , I will explain first what is the dialog system, what was the problem we had to face, how we tackled it, what we have done, what we haven’t and finally, which outcome we got.

I am receptive to any doubt, critics or suggestions from you, so just raise your hand and you’ll be happily answered

What is the dialog system?

I think that almost everyone reading this post and who have played beforehand adventure games like “Monkey Island” will understand what I mean. The idea behind this system is give support to dialog trees (although dialogues are not really trees) implementation. That is, when you interact or talk with an NPC, the player can choose which subject he or she want to talk about till the conversation is over. These conversations can help us to obtain more information, go forward in the game and even, depending on our questions and answers, affect the final outcome (be careful with your responses during the game, we could use them in next chapters)

Image

The problem

The first problem and the easiest to notice from the point of view of a player who has played chapter 1, it’s that in the pilot chapter there wasn’t anybody to talk to. So, first thing we needed to do was to implement dialogues within the game but that’s not all, we also required a friendly tool to make the dialogues easy to design and test (chat simulations) for the game designers since the programmers we were too busy as to be loaded with an extra task. And everything was to be done in two or three week at the most. Quite enough, isn’t it?

The workflow we had in mind was the following:

Image

What have we implemented?

At engine level

Starting from the bottom up, we designed a graph data structure which in turn extended and used our actions system. So this way we had again something similar to a BehaviorTree (BT) but Attention! those with a minimal knowledge about graphs will know that a (as its name implies) BT is acyclic, while many of our conversations had cycles. Thus, we needed to push things a little bit more in our actions system. Basically, what we have now is a directed labeled graph consisting of nodes with a destination edge pointing to the next node. Each node has the following structure:

Image

This time, we have separated a bit more the structure (graph) from the data (actions).
Let’s explain a couple of things first:

  • Condition. This is a kind of Action which will check whether the necessary conditions are met to execute the node or not. There are two types of conditions; the “blocking” and the “passthrough”. In the first type, if the condition is not met the dialogue ends. In the second type, what happens is that the internal dialogue logic doesn’t execute, so it automatically goes to its neighbor node/destination.
  • Dialogue actions. Up to the present day, there are 3:
    • Say. An actor says something in the dialogueImage
    • Select Choice. Choose an answer, question or topic (​​destination edge) on which to continue the dialogueImage
    • Jump selector. Given a set of edges, take the destination nodes and check if they meet their condition or in the case they don’t, check if they are not blocking conditions. Choose the first node that meets the constraint. If none satisfies it, use the default destination which is normally the end of the conversation.Image

At tools level

Honestly, most part of our implementation was a Mauricio’s idea. Completely refusing to reinvent the wheel, he introduced me Chat Mapper (http://www.chat-mapper.com/), which with its standard commercial licence you can write your own exporters in C#. But not only that, it also allows to insert LUA code portions, providing some extra logic to dialogues.So we finally opted to use the great default power of this tool just to only focus in writing an exporter which could be able to generate us an ActionScript class coming from a finished dialogue in that tool. Well, not just an only class but something like this:

Image

Let’s overview the parts of this exporter:

  • Localization. It generates a localization file with the dialogue texts.
  • LUA Parser. One of my favorite parts, using ANTLR (http://www.antlr.org/), We have implemented a parser of the LUA subset supported by ChatMapper so we can “translate” that code to an Abstract Syntax Tree (AST), which by a TreeParser can be used to build our tree of ActionScript actions. Yes, we moved from LUA to ActionScript via C #.Image
  • Animations. In ChatMapper we can indicate just from a file which action tree must be used when a specific sentence it’s said, if that tree doesn’t exist, a new empty one is created by default. If the animations file does not exist either, again it is created by default. Hereunder you’ll find a simple example of an animations file :

    var show_postcard : Vector.<Action> = new <Action>
    [
    new PlayCharacterAnimationAction( "Player", "up_left_hand_ping", true )
    ];
    var mery_comes : Vector.<Action> = new <Action>
    [
    new MoveAction( 465, 475, null, NPC_MERY_VINGE, true, false, false ),
    new MoveAction( 650, 475, 1, NPC_MERY_VINGE, true, false, false, false),
    new WaitAction( 500 ),
    new PlayCharacterAnimationAction( “Player”, “up_left_hand_pong”, true ),
    new MoveAction( 465, 475, null, NPC_MERY_VINGE, true, false, false ),
    new MoveAction( 465, 460, null, NPC_MERY_VINGE, false, false, false, true ),
    new PlayCharacterAnimationAction( NPC_MERY_VINGE, “sitting” )
    ];

What have we not implemented?

At engine level

We decided not to implement a generic graph data structure mainly because we had a very specific problem, moreover, keeping this in mind, we had the perfect excuse to continue improving our BTs library (as for instance, splitting tree struture from the actions).

We haven’t any debugger/simulator beyond the one of the game itself, so if we already had that one of ChatMapper, we couldn’t afford to spend our scarce time in an unnecessary feature at that moment.

At tools level

First of all, my main idea was to make something like what our friend fellows from Autoloot Games made here: http://autoloot-games.com/?p=110. The idea was to try using again Brainiac as a design tool, but the fact of having to make a debugger and an exporter was a time wasting option. In addition, firstly we had to make brainiac support simple cycles easily.

Results

What went well

Again, I think that the most remarkable thing has been to achieve an easy to use tool, allowing us to add dialogues in future chapters.

What went wrong

One of the aspects that we could classify as negative, it’s been the poor optimization performed when saving data dialogues. Everyone who have played through chapter 2, you’ll have noticed that at the beginning of the game you were asked to allow more space storage (we fell short with only 100k ). Although we don’t need that huge requested space (is set by flash) I think that with little common sense we could reduce that space significantly.

Despite of all the simplicities provided by ChatMapper, there is something that it didn’t go as well as we expected. Taking into account the ability to add LUA logic (which for us was a must) to the dialogues, the person importing or translating dialogue texts to the tool needs a minimum of understanding in programming.

Closing comments

Again for reading the whole post here’s your prize. A video I’ve done this morning showing the basics of our exporter.