This is an old revision of the document!
Start Page » Game Development with the Drag[en]gine » Simple Conversation
Behavior in action
Simple conversations provide a quicker and easier way to create simple conversations compared to the IGDE Conversation Editor. In contrary to regular conversations simple conversations are created using XML files. Yet they are still regular conversations but using an XML syntax and a converter which creates regular conversations for you. It is important to note that simple conversations already require a regular conversation to be present. The reason is that simple conversation reuse various definitions present inside regular conversations like camera shots, gestures, look-at targets as well as pre-made topics for reuse. In the examples below it is expected such a regular conversation is present and contains the required camera shots, gestures and look-at targets.
Conversations in general compose of a series of actors speaking with camera angle changes in between. Furthermore actors do mouth animation, perform gestures, perform facial animation and looking at the currently speaking actor or other targets. For the majority of conversations the same type of camera shots are used with the same delays. This process can be sped up by generating actor speaking and camera changes according to common rules. Also speaking gestures or automatically looking at whatever actor is speaking is a common task that can be automated. All this is done by the simple conversation system to make conversations faster to build for which you do not need full control.
To achieve this simple conversations uses these main facilities:
Camera definitions provide a list of camera shots or other types of camera changes. Upon using a camera a random shot is selected from the list of possible camera shots. You can use camera shots, conversation snippets, game commands and actor commands to change a camera. By randomly picking from a list of possible camera shots conversations are quickly augmented in fidelity without extra work.
Actor definitions define what actor is speak, formating information and what camera to use. Upon encountering an actor tag the camera definition linked to the actor is used to produce a camera shot conversation action. Then an actor speak conversation action is created. The action is set up with the appropriate parameters and styles defined in the actor definition. Furthermore a default set of gestures, face poses and look-ats can be defined. These will be used unless actor tags define their own. This way actors will perform default actions while speaking which already increases fidelity a lot.
Hence actor definitions are like blueprints of actor speak conversation actions you usually have to manually create (or typically copy around). Using actor definitions you can also preconfigure typical moods like an actor thinking something or shouting. The required settings can be stored in multiple actor definitions and used as blueprint.
This is where the actual conversations are defined In contrary to regular conversations which contain topic groups which contain topics a simple conversation contains only snippets. This simplifies the process of working with conversations for common tasks. This is no real restriction since you can always fold regular conversation topic-group → topic identifiers into a snippet for example like topic-group:topic
or similar formating rules. What you do here is up to you.
Important to note is that inside simple conversation snippets you can also run regular conversation snippets using topic-group and topic identifiers. You can thus extend simple conversation with pre-made regular conversations where it makes sense.
The main workflow of creation simple conversations has been designed to align with how conversations are typically created. This accelerates the process of creating such conversations in XML form.
First let's start with some example camera and actor definitions. You usually create them once and store them in a file you can include as basics to use. Here the definitions used for the examples to come:
<camera id='player actor0'> <delay>0.25</delay> <cameraShot cameraTarget='actor0 medium' lookAtTarget='player medium' duration='20'>ots left medium</cameraShot> </camera> <camera id='actor0 player'> <delay>0.25</delay> <cameraShot cameraTarget='player medium' lookAtTarget='actor0 medium' duration='20'>ots right medium</cameraShot> </camera> <actor id='player actor0'> <actorId>player</actorId> <camera>player actor0</camera> </actor> <actor id='actor0 player'> <actorId>actor0</actorId> <camera>actor0 player</camera> </actor>
Here ots
means over the shoulder
which is an often used camera shot used in movie and tv productions. actor0
is the npc the player is talking to. These camera shots are only going to choose from one single camera shot. By adding more than one camera shot to each camera definition the shots would be randomized.
With this out of the way let's head over to a conversation text grouped by actor. This is what you usually start out with in text editors when you plan a conversation. This is an example:
<snippet id='nono_namaos.yourself2'> georgo: For how long are you working here already? nono: Has to be 15 or 16 years. georgo: Not bad at all. Have you been tinkering around all this time? nono: Most certainly I did. I'm responsible for all technical things around here. No matter if devices or computers I ensure everything is working as it should and is secure. Sometimes I even do programming work on some of Odjin's implants. </snippet>
Basically you wrote down who is telling what and in what order. So far we are already close to working simple conversation but not there yet.
As next step replace the actor speaking notes with actual actor tags. Here you have to possibilities: the long tags and the short tags. In the next text the first line speech uses the long tag form and the others the short tag form:
<snippet id='nono_namaos.yourself2'> <actor id='player actor0'/> For how long are you working here already? <a i='actor0 player'/> Has to be 15 or 16 years. <a i='player actor0'/> Not bad at all. Have you been tinkering around all this time? <a i='actor0 player'/> Most certainly I did. I'm responsible for all technical things around here. No matter if devices or computers I ensure everything is working as it should and is secure. Sometimes I even do programming work on some of Odjin's implants. </snippet>
As you can see the short version makes your simple conversation files shorter and easier to read. For this reason some tags have short versions. You can also see the actor tags are empty and not wrapping the affecting text. This design choice makes it easier to sprinkle the tags into the text at the desired location without needing to deal with correctly wrapping text.
Now the simple conversation knows what actor is speaking and what actor definitions to use to generate the conversation actions. If you would run this simple conversation right now you would get 4 speeches because the last three lines are collapsed into one. This is because simple conversations ignore whitespaces like HTML does. Hence the last three lines become one. But might want to show them as 3 individual speeches performed by the same actor. To achieve this you have to add some more actor tags at the end of the line (or the start of the next) to separate them. These actor tags are empty which means to repeat the last actor tag used but without camera change. The result looks now like this:
<snippet id='nono_namaos.yourself2'> <actor id='player actor0'/> For how long are you working here already? <a i='actor0 player'/> Has to be 15 or 16 years. <a i='player actor0'/> Not bad at all. Have you been tinkering around all this time? <a i='actor0 player'/> Most certainly I did. I'm responsible for all technical things around here.<a/> No matter if devices or computers I ensure everything is working as it should and is secure.<a/> Sometimes I even do programming work on some of Odjin's implants. </snippet>
As you can see two instances of <a/>
have been added. Now the speech is split into 3 individual speeches instead of 1 large speech. Depending on your needs both situations are viable. You could also use the long tag <actor/>
but <a/>
is shorter.
This simple conversation would be already playing out. If the ECBehaviorConversationActor added to each actor contains a speech animation then the simple conversation system uses the words in the text to create mouth animations and to determine how long an actor is speaking. Without speech animation no mouth animation is done and the length of speech is estimated.
You can now spice things up by adding gestures, face poses and look-ats. You can do this in the actor definition or the snippet itself. By doing in the action definition you do not have to repeat them all the time. Let's update the actor definition:
<actor id='player actor0'> <actorId>player</actorId> <camera>player actor0</camera> <lookAt>actor0 close</lookAt> <gesture>speak</gesture> <facePose>neutral</facePose> </actor> <actor id='actor0 player'> <actorId>actor0</actorId> <camera>actor0 player</camera> <lookAt>player close</lookAt> <gesture>speak</gesture> <facePose>neutral</facePose> </actor>
Now the actors will look at the other actor when they speak. Another solution for doing this is to use behaviors which automatically track speaking actors and update looking to face them. For this discussion we keep it simple and do it here.
To extend this example a bit more let's modify the actual conversation and force a different gesture for one actor:
<snippet id='nono_namaos.yourself2'> <actor id='player actor0'/> For how long are you working here already? <a i='actor0 player'/> Has to be 15 or 16 years. <a i='player actor0'/> <g i='thumbs up'/> Not bad at all.<g i='speak'/> Have you been tinkering around all this time? <a i='actor0 player'/> <g i='agree'/><g i='speak'/> Most certainly I did. I'm responsible for all technical things around here.<a/> No matter if devices or computers I ensure everything is working as it should and is secure.<a/> <f i='happy'/> Sometimes I even do programming work on some of Odjin's implants. </snippet>
Here some g
tags haven been added (long form gesture
with attribute id
). On the affected lines the gestures defined in the actor definition are ignored and the provided ones used. Two versions are shown here.
The first version puts the gestures in a specific location in the text. The simple conversation system will add the gestures with the correct duration to make the be in sync with the mouth animation. For such gestures using held gestures works best. Not held gestures will stretch in time which can look silly depending on how much they are stretched. Held gestures play on until finished and thus keep their normal pacing.
The second form places both gestures right behind each other. This works best with non-held gestures. The simple conversation system puts the gestures behind each other with their duration set to their default duration. The default duration is stored in the regular conversation file where the gesture is defined. The second form works best if the last gesture is a held one. The gestures will play one after the other with the last one held out long. This does not necessarily line up with the mouth animation but it is a typical design for visual novel type conversations. As a side note. If more than one gesture is added to an actor definition then they play out like the second form, hence one played after the other.
The f
tag is the short form for facePose
. The l
tag would be the short form for lookAt
but this one is not used in the example above.
Let's modify the text a bit to cover a special case:
<snippet id='nono_namaos.yourself2'> <actor id='player actor0'/> For how long are you working here already? <a i='actor0 player'/> Has to be 15 or 16 years. <a i='player actor0'/> <g i='thumbs up'/> Not bad at all.<g i='speak'/> Have you been tinkering around all this time? <a i='actor0 player'/> <g i='agree'/><g i='speak'/> Most certainly I did. I'm responsible for all {actorProfession} around here.<a/> No matter if devices or computers I ensure everything is working as it should and is secure.<a/> Sometimes I even do programming work on some of Odjin's implants. </snippet>
The text technical things
has been now replaced with a conversation system tag. ECBCTRRBindings allows to adds rules which allow to replace such text in conversations with dynamic content. Depending on what kind of information you need to add these tags can be complex with parameters and what not else. Trying to use speech animation to speak them does not make sense. To solve this problem t
tags (or long tag
with attribute anim
) exist. They wrap such tags and tell the simple conversation system what text they should use instead of them for conversation purpose. The example would then look like this:
<snippet id='nono_namaos.yourself2'> <actor id='player actor0'/> For how long are you working here already? <a i='actor0 player'/> Has to be 15 or 16 years. <a i='player actor0'/> <g i='thumbs up'/> Not bad at all.<g i='speak'/> Have you been tinkering around all this time? <a i='actor0 player'/> <g i='agree'/><g i='speak'/> Most certainly I did. I'm responsible for all <t a='something something'>{actorProfession}</t> around here.<a/> No matter if devices or computers I ensure everything is working as it should and is secure.<a/> Sometimes I even do programming work on some of Odjin's implants. </snippet>
Now the tag has been wrapped in a t
tag with the attribute indicating what text should be spoken (and used for measuring speech length). With this the simple conversation would be ready to be used. Behaviors like ECBehaviorConversation are able to run simple conversations using a regular conversation as base. There are many other tags supported. The description of them is outlined below.
With the simple conversation working one last thing to do sooner or later is translations to make the game available to people speaking a different language. Regular conversations require using language packs. This is the typical way translations are done. For large conversations this can be cumbersome to use.
Simple conversation provide a nifty way to handle this. You can create a second simple conversation file which you load only if a specific language is used in your game. You load then first the original simple conversation and then the translated one. By calling SimpleConversation.importTranslation() you can then import the translated simple conversation and “patch” the original simple conversation with it.
Remember the dialog text with which our example started out with? You can take nearly the same text but skip the actor notes and just translate the lines. The result is looking then like this:
<snippet id='nono_namaos.yourself2'> Wie lange arbeitest du schon hier? 15 oder 16 Jahre. Nicht schlecht. Und die ganze Zeit am tüffteln? Kann man so sagen. Ich bin hier für die technischen Dinge zuständig. Ob Geräte oder Computer, ich sorge dafür, dass alles funktioniert und sicher ist. Selbst an Odjin's Implantaten muss ich manchmal rum programmieren. </snippet>
That's pretty close to what we need for the translation to be usable. Here too we have the problem that without separating the text lines the simple conversation system does not know where one actor speak starts and the other ends. Simple add <a/>
after each end of spoken line (the last line does not need one). The result looks now like this:
<snippet id='nono_namaos.yourself2'> Wie lange arbeitest du schon hier?<a/> 15 oder 16 Jahre.<a/> Nicht schlecht. Und die ganze Zeit am tüffteln?<a/> Kann man so sagen. Ich bin hier für die technischen Dinge zuständig.<a/> Ob Geräte oder Computer, ich sorge dafür, dass alles funktioniert und sicher ist.<a/> Selbst an Odjin's Implantaten muss ich manchmal rum programmieren. </snippet>
And that's it. This file is now a valid translated snippet. When you patch an original simple conversation like this you get the translation properly applied. What happens under the hood? The simple conversation system walks over all actor speeches in the original file. It will then apply, one by one, the lines actor speeches from the translated file and update the original line with it. It is thus important the translated conversation has the exact same count of actor speech lines as the original. Otherwise the mapping is wrong.
What about gestures, face pose, look-ats and t
tags? Simple drop them all. In the translation only text has to be present and no tags (except <a/>
to end a line). This makes simple conversation files easy to translate for translation companies. Simply paste the translated text into your snippet
tags and add the <a/>
tags at the end of the lines and you are all set.
The simple conversation file format is recognized by the LoadSimpleConversation script class. The file is an XML file with a simple structure to define a simple conversation using XML.
Tag | Description | Occurance | Default |
---|---|---|---|
import | Load simple conversation using path from tag text content. Replaces elements with same name if present. | 0..N | - |
camera | Define camera. Replaces camera with same name if present. | 0..N | - |
actor | Define actor. Replaces actor with same name if present. | 0..N | - |
snippet | Define snippet. Replaces snippet with same name if present. | 0..N | - |
Defines a camera. Can contain one or more camera shot definitions to randomly choose one.
Attribute | Description | Occurance | Default |
---|---|---|---|
id | Name of camera. | Required | - |
Tag | Description | Occurance | Default |
---|---|---|---|
cameraShot | Add camera shot from regular conversation. Attributes:
| 0..N | - |
snippet | Add camera shot by running a simple or conversation snippet. Attributes:
| 0..N | - |
command | Add camera shot by running a game or actor command. Attributes:
| 0..N | - |
delay | Delay in seconds for created camera shot action. | 0..1 | 0.25 |
Defines an actor.
Attribute | Description | Occurance | Default |
---|---|---|---|
id | Name of actor. | Required | - |
Tag | Description | Occurance | Default |
---|---|---|---|
actorId | Conversation actor identifier or alias. | 1 | - |
camera | Name of camera definition to use. If not set no camera switch is used. | 0..1 | - |
style | Text box style to use. | 0..1 | empty string |
gesture | Identifier of gesture to add to play for each new speech line if not overwritten in the speech line. Gestures are played one behond the other with the last one stretched to the speech length. | 0..N | - |
facePose | Identifier of face pose to use for each new speech line if not overwritten in the speech line. | 0..1 | empts string |
lookAt | Identifier of head/eye look-at to use for each new speech line if not overwritten in the speech line. | 0..1 | empty string |
delay | Delay in seconds for created action shot action. | 0..1 | 0.25 |
prolongLastGesture | Increase the duration of the last gesture played in a speech line by this many seconds. This makes gestures play a bit longer than the mouth animation played which is more natural. | 0..1 | 0 |
useSpeechAnimation | Use speech animation to animate mouth. Typically for thinking speech animation has to be disabled. | 0..1 | true |
Defines a conversation snippet.
Attribute | Description | Occurance | Default |
---|---|---|---|
id | Name of snippet. | Required | - |
Tag | Description | Occurance | Default |
---|---|---|---|
actor | Switch speaking actor. Adds a camera change if the actor definition contains one. Attributes:
| 0..N | - |
a |
Short version of
| 0..N | - |
gesture | Add gesture to play back. Replaces gestures defined in active actor definition. Attributes:
| 0..N | - |
g |
Short version of
| 0..N | - |
facePose | Add face pose to play back. Replaces face poses defined in active actor definition. Attributes:
| 0..N | - |
f |
Short version of
| 0..N | - |
lookAt | Add head/eyes look-at to play back. Replaces look-ats defined in active actor definition. Attributes:
| 0..N | - |
l |
Short version of
| 0..N | - |
tag | Define animation text to use for tag text content. Used for dynamic text special tags to get a usable mouth animation. Attributes:
| 0..N | - |
t |
Short version of
| 0..N | - |
command | Run game or actor command using text content of tag. Attributes:
| 0..N | - |
stopTopic | Stop simple conversation topic. Continues conversation after the action running the simple conversation snippet. | 0..N | - |
stopConversation | Stop conversation. | 0..N | - |
variable | Set conversation playback variable or actor parameter to tag content text. Tag content text can be of this form:
Tag Attributes:
| 0..N | - |
trigger | Operate trigger. Attributes:
| 0..N | - |
if |
Begin if-else block. Block ends at the next line which is not
| 0..N | - |
elif | Continue if-else block with an elif clause. Attributes:
| 0..N | - |
else | Continues if-else block with an else clause then closes block. Attributes:
| 0..N | - |
choice |
Begins player choice block. Blocks ends at the next line which is not
| 0..N | - |
option |
Continues player choice block with the next option. Option is only added if no condition is
| 0..N | - |
wait |
Wait until any condition becomes
| 0..N | - |
snippet |
Run regular or simple conversation snippet. Topic or identifier is text content. For simple conversation snippet is added directly to current snippet and
| 0..N | - |
music | Switch music using name from content text. | 0..N | empty string |
add | Add actor or coordinate system. Attributes:
| 0..N | - |
remove | Remove actor or coordinate system. Attributes:
| 0..N | - |
pause | Add pause with content text as length in seconds. Effect depends on where the tag is used:
If you want a pause after a speech line to not affect the speech line but the next action use | 0..N | - |
p | Short version of pause tag. | 0..N | - |
endActorSpeak | End last actor speech line. Required to apply pause tag to the next tag instead of the speec line. | 0..N | - |
music | Switch music using name from content text. | 0..N | empty string |
waitMode | Switch wait mode. Affects how the next tags set waiting of generated conversation actions. Valid values:
| 0..N | - |
Content text is used as actor speech lines. If actor speech line contains no words (empty line) then the line is skipped. Hence whitespaces and newlines are collapsed into a single whitespace similar to HTML.
Adds a conversation playback variable or actor parameter condition to if
, elif
, option
or wait
.
Attribute | Description | Occurance | Default |
---|---|---|---|
name | Name of playback variable or actor parameter to evaluate. | Required | - |
actor | If set use parameter from conversation actor actor . Otherwise use playback variable. | Optional | - |
test | Test to apply to value. Can be of this form:
| Required | - |
Adds a trigger condition to if
, elif
, option
or wait
.
Attribute | Description | Occurance | Default |
---|---|---|---|
name | Name of trigger to evaluate. | Required | - |
test | Test to apply to trigger state. Allowed values:
| Required | - |
Adds a game or actor command condition to if
, elif
, option
or wait
. Command to run is content text.
Attribute | Description | Occurance | Default |
---|---|---|---|
actor | If set test condition of conversation actor actor . Otherwise test game condition. | Optional | - |
test | Test to apply to result of condition. Allowed values:
| Required | - |
Adds a has actor condition to if
, elif
, option
or wait
.
Attribute | Description | Occurance | Default |
---|---|---|---|
actor | Test if conversation actor with id or alias actor is present. | Required | - |
test | Test to apply to result of condition. Allowed values:
| Required | - |
Adds a logic all condition to if
, elif
, option
or wait
. Condition evaluates to true
if all child conditions evaluate to true. If no child conditions are present condition evaluates to false
.
Adds a logic any condition to if
, elif
, option
or wait
. Condition evaluates to true
if one or more child conditions evaluate to true.
Adds a logic none condition to if
, elif
, option
or wait
. Condition evaluates to true
if no child condition evaluate to true.