{"id":248,"date":"2015-01-17T08:35:34","date_gmt":"2015-01-17T06:35:34","guid":{"rendered":"http:\/\/reyn.vlietstra.co.za\/?page_id=248"},"modified":"2022-02-01T20:40:01","modified_gmt":"2022-02-01T18:40:01","slug":"dialog-framework","status":"publish","type":"page","link":"https:\/\/reyn.vlietstra.co.za\/dialog-framework","title":{"rendered":"Fluent Dialogue"},"content":{"rendered":"\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large is-resized\"><a href=\"https:\/\/reyn.vlietstra.co.za\/wp-content\/uploads\/2015\/01\/FluentLogo.png\"><img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/reyn.vlietstra.co.za\/wp-content\/uploads\/2015\/01\/FluentLogo.png\" alt=\"\" class=\"wp-image-665\" width=\"258\" height=\"170\" srcset=\"https:\/\/reyn.vlietstra.co.za\/wp-content\/uploads\/2015\/01\/FluentLogo.png 842w, https:\/\/reyn.vlietstra.co.za\/wp-content\/uploads\/2015\/01\/FluentLogo-300x197.png 300w, https:\/\/reyn.vlietstra.co.za\/wp-content\/uploads\/2015\/01\/FluentLogo-768x505.png 768w, https:\/\/reyn.vlietstra.co.za\/wp-content\/uploads\/2015\/01\/FluentLogo-304x200.png 304w\" sizes=\"(max-width: 258px) 100vw, 258px\" \/><\/a><\/figure><\/div>\n\n\n<p><iframe loading=\"lazy\" width=\"850\" height=\"650\" style=\"border: 1px solid black;\" src=\"https:\/\/reyn.vlietstra.co.za\/wp-content\/uploads\/Reyn\/WebGL\/FluentDialog\/index.html\" frameborder=\"1\" allowfullscreen=\"allowfullscreen\"><\/iframe><\/p>\n<p>After the WebGL above loads, click on it. Use the W\/A\/S\/D keys to move E to initiate conversation<\/p>\n<div class=\"responsive-tabs\">\n<h2 class=\"tabtitle\">Overview<\/h2>\n<div class=\"tabcontent\">\nFluent Dialogue is a dialogue\u00a0conversation\u00a0framework for unity. Conversations are defined using a <a href=\"http:\/\/en.wikipedia.org\/wiki\/Fluent_interface\" target=\"_blank\" rel=\"noopener\">fluent api<\/a> in code.<\/p>\n<p>The unity asset is available for free on the unity asset store <a href=\"https:\/\/assetstore.unity.com\/packages\/tools\/gui\/fluent-dialogue-30069\" target=\"_blank\" rel=\"noopener\">here<\/a><\/p>\n<h3>Features<\/h3>\n<ul>\n<li>Speech bubbles<\/li>\n<li>Conversation trees<\/li>\n<li>Multilingual<\/li>\n<li>User definable UI<\/li>\n<li>Define variables and logic directly in C#<\/li>\n<\/ul>\n\n<\/div><h2 class=\"tabtitle\">0<\/h2>\n<div class=\"tabcontent\">\n\n<h3>0: Hello World!<\/h3>\n<h6><strong>Code<\/strong><\/h6>\n<p>To create a FluentScript we inherit from <strong>FluentScript<\/strong>, which is a Monobehaviour, and override the Create( ) method. In this first example the object this script is placed on will Yell &#8220;Hello World&#8221; when the script is executed.<\/p>\n<pre class=\"toolbar:1 lang:c# decode:true\" title=\"0: Hello World!\">using Fluent;\n\npublic class Conversation0 : FluentScript\n{\n  public override FluentNode Create()\n  {\n    return Yell(\"Hello World!\");\n  }\n}<\/pre>\n<h6><strong>Setup<\/strong><\/h6>\n<p>Add an empty GameObject to the object you want to yell. Here the object that will yell is called NPC 0 and the empty game object is called Talk.<\/p>\n<p><a href=\"https:\/\/reyn.vlietstra.co.za\/wp-content\/uploads\/2015\/01\/objecttree.png\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone\" src=\"https:\/\/reyn.vlietstra.co.za\/wp-content\/uploads\/2015\/01\/objecttree.png\" alt=\"\" width=\"151\" height=\"81\" \/><\/a><\/p>\n<p>We then add the Conversation 0 script to Talk. In this example talk also needs a collider so that we know when we are close enough to talk to NPC 0.<br \/>\u00a0<a href=\"https:\/\/reyn.vlietstra.co.za\/wp-content\/uploads\/2015\/01\/fluentscript0.png\"><img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/reyn.vlietstra.co.za\/wp-content\/uploads\/2015\/01\/fluentscript0.png\" alt=\"\" width=\"393\" height=\"213\" \/><\/a>\u00a0<br \/><br \/>Yell shows the first canvas it finds in Talk. It then sets the first Text it finds within that canvas to &#8220;Hello World&#8221;. Note that the FluentScript&#8217;s output is presented as a tree under &#8220;Root&#8221;.<\/p>\n<h6><strong>Initiating the conversation<\/strong><\/h6>\n<p>To initiate a conversation we need to call Run( ) on the FluentScript. You can do that any way you&#8217;d like, but for the examples there is a script called FluentManager. If you would like to use FluentManager then add an empty GameObject to your scene and add FluentManager to it.<br \/><a href=\"https:\/\/reyn.vlietstra.co.za\/wp-content\/uploads\/2015\/01\/fluentmanager.png\"><img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/reyn.vlietstra.co.za\/wp-content\/uploads\/2015\/01\/fluentmanager.png\" alt=\"\" width=\"394\" height=\"111\" \/><\/a> <br \/><br \/>On FluentManager set the Text<br \/>UI element that will notify the player that there is something to talk to, as well as set your player.\u00a0<\/p>\n\n<\/div><h2 class=\"tabtitle\">1<\/h2>\n<div class=\"tabcontent\">\n\n<h3>1: OnStart() and OnFinish()<\/h3>\n<pre class=\"toolbar:1 lang:c# decode:true \">public class Conversation1 : FluentScript\n{\n    public override void OnStart() { Player.Instance.CanMove = false; }\n    public override void OnFinish() { Player.Instance.CanMove = true; }\n\n    public override FluentNode Create()\n    {\n        return Yell(\"Now you can't move while I talk!\");\n    }\n}<\/pre>\n<h6><strong>Code<\/strong><\/h6>\n<p>Override OnStart and OnFinish to specify what should happen before and after a <strong>FluentScript<\/strong> starts and ends. Here we disable player movement.<\/p>\n<h6>Encapsulate<\/h6>\n<p>Since we always want the player not to move when a converstation starts we encapsulate that information in a new class called MyFluentDialogue<\/p>\n<pre class=\"toolbar:1 lang:c# decode:true\" title=\"0: Hello World!\">using Fluent;\n\npublic abstract class MyFluentDialogue : FluentScript\n{\n    public override void OnFinish() { Player.Instance.CanMove = true; }\n    public override void OnStart() { Player.Instance.CanMove = false; }\n}<\/pre>\n<p>We will from now on inherit from <strong>MyFluentDialogue<\/strong>\u00a0instead of <strong>FluentScript<\/strong><\/p>\n\n<\/div><h2 class=\"tabtitle\">2<\/h2>\n<div class=\"tabcontent\">\n\n<h3>2: Response Chain<\/h3>\n<pre class=\"toolbar:1 lang:c# decode:true \">public class Conversation2 : MyFluentDialogue\n{\n    public override FluentNode Create()\n    {\n        return\n            Yell(\"I love ...\") *\n            Yell(\"CAKE!\") *\n            Yell(\"And chained responses!\");\n    }\n}<\/pre>\n<h6><strong>Code<\/strong><\/h6>\n<p>Yell is one of many <strong>FluentNode<\/strong>s, we can chain nodes. In this case we yell 3 times. A <strong>FluentNode<\/strong> completes before the next one in the chain is executed. Note that we need to use * to join them.<\/p>\n\n<\/div><h2 class=\"tabtitle\">3<\/h2>\n<div class=\"tabcontent\">\n\n<h3>3: Others Yell<\/h3>\n<pre class=\"toolbar:1 lang:c# decode:true\">public class Conversation3 : MyFluentDialogue\n{\n    public GameObject player;\n    public GameObject npc4;\n\n    public override FluentNode Create()\n    {\n        return\n            Yell(\"Anyone can yell!\") *\n            Yell(player, \"Oh!\") *\n            Yell(player, \"Mine looks different!\") *\n            Yell(npc4, \"Mine is a billboard!\").Billboard();\n    }\n}<\/pre>\n<h6><b>Code<\/b><\/h6>\n<p>Yell takes an optional parameter to specify the object that should do the yelling. Note that the specified object should have a canvas with a Text UI element.<\/p>\n\n<\/div><h2 class=\"tabtitle\">4<\/h2>\n<div class=\"tabcontent\">\n\n<h3>4: Options Presenter<\/h3>\n<pre class=\"toolbar:1 lang:c# decode:true\">public class Conversation4 : MyFluentDialogue\n{\n    public override FluentNode Create()\n    {\n        return\n            Yell(\"I'm looking for my cat\") *\n            Yell(\"Have you seen her ?\") *\n            Show() *\n            Options\n            (\n                Option(\"Nope\") *\n                    Hide() *\n                    Yell(\";-(\") *\n                    End() *\n\n                Option(\"Should I go find her ?\") *\n                    Hide() *\n                    Yell(\"Yes please!\") *\n                    Yell(\"I'd prefer a persian!\") *\n                    End()\n             );\n    }\n}<\/pre>\n<h6>Code<\/h6>\n<p>In this example we introduce a new <strong>FluentNode<\/strong>\u00a0called Options( ), which contain one or more Option( ) <strong>FluentNodes<\/strong>. Option( )&#8217;s first argument specifies the text that will be presented to the user. The <strong>FluentNodes<\/strong>\u00a0following an Option( ) will be executed when that option is selected. Options are presented by an OptionsPresenter.<\/p>\n<h6><strong>Setup<\/strong><\/h6>\n<p>An\u00a0OptionsPresenter script needs to be added to your Talk object to show options.<br \/><a href=\"https:\/\/reyn.vlietstra.co.za\/wp-content\/uploads\/2015\/01\/optionspresenter2.png\"><img decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-707 alignnone\" src=\"https:\/\/reyn.vlietstra.co.za\/wp-content\/uploads\/2015\/01\/optionspresenter2.png\" alt=\"\" width=\"394\" height=\"487\" srcset=\"https:\/\/reyn.vlietstra.co.za\/wp-content\/uploads\/2015\/01\/optionspresenter2.png 394w, https:\/\/reyn.vlietstra.co.za\/wp-content\/uploads\/2015\/01\/optionspresenter2-243x300.png 243w, https:\/\/reyn.vlietstra.co.za\/wp-content\/uploads\/2015\/01\/optionspresenter2-162x200.png 162w\" sizes=\"(max-width: 394px) 100vw, 394px\" \/><\/a>\u00a0<br \/><br \/>On the <strong>OptionsPresenter<\/strong>\u00a0you specify 3 things<\/p>\n<ol>\n<li><em>Dialog UI<\/em> is the UI element that will be SetActive when the Show() or Hide() <strong>FluentNodes<\/strong> are executed.<\/li>\n<li><em>Option Item UI<\/em> is a prefab that will be used for your Option Items. The Option Item prefab needs to have a Text component, which will be set to the specified option text.<\/li>\n<li><em>Options Panel<\/em>\u00a0is the panel that will be used as the container of the option items<\/li>\n<\/ol>\n\n<\/div><h2 class=\"tabtitle\">5<\/h2>\n<div class=\"tabcontent\">\n\n<h3>5: Write<\/h3>\n<pre class=\"toolbar:1 lang:c# decode:true\">public class Conversation5 : MyFluentDialogue\n{\n    public Text OtherTextElement;\n\n    public override void OnFinish()\n    {\n        OtherTextElement.text = \"\";\n        base.OnFinish();\n    }\n\n    public override FluentNode Create()\n    {\n        return\n            Show() *\n            Write(0, \"&lt;color=#0000ffff&gt;Write writes to a text element\") *\n\n            Options\n            (\n                Option(\"This dialog looks different!\") *\n                    Write(0.5f, \"Yes!\") *\n                    Write(\"Dialogs and options are user definable prefabs!\\nYou need to press a button to continue this Write\").WaitForButton() *\n\n                Option(\"Write to an element specified in code\") *\n                    Write(OtherTextElement, 0, \"This text element is specified in code!\") *\n\n                Option(\"Bye\") *\n                    Hide() *\n                    Yell(\"Bye bye!\") *\n                    End()\n             );\n    }\n}<\/pre>\n<h6><strong>Code<\/strong><\/h6>\n<p>Here we introduce a new <strong>FluentNode<\/strong>. The Write node will write text to a specified UI element.<\/p>\n<h6><strong>Setup<\/strong><\/h6>\n<p>We need to add a WriteHandler to the talking object.<br \/><a href=\"https:\/\/reyn.vlietstra.co.za\/wp-content\/uploads\/2015\/01\/write.png\"><img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/reyn.vlietstra.co.za\/wp-content\/uploads\/2015\/01\/write.png\" alt=\"\" width=\"394\" height=\"564\" \/><\/a>\u00a0<br \/><br \/>There are 3 things we can specify on Write Handler<\/p>\n<ol>\n<li><em>Text UI<\/em> is the Text UI element the text will be written to<\/li>\n<li><em>Seconds \/ Character<\/em> is the delay per character while writing<\/li>\n<li>Optionally <em>Button Element<\/em>\u00a0is the button that will be shown after the text has been written. The user will have to press the button before execution continues<\/li>\n<\/ol>\n\n<\/div><h2 class=\"tabtitle\">6<\/h2>\n<div class=\"tabcontent\">\n\n<h3>6: Branching<\/h3>\n<pre class=\"toolbar:1 lang:c# decode:true\">public class Conversation6 : MyFluentDialogue\n{\n    public GameObject redGuy;\n\n    public override FluentNode Create()\n    {        \n        return\n            Show() *            \n\n            Options\n            (\n                Write(0, \"Lets look at an example with multiple branches\") *\n                Option(\"That red guy...\") *\n                    Write(0, \"What about him ?\") *\n                    Options\n                    (\n                        Option(\"Whats his name ?\") *\n                            Write(0, \"He's just an extra in the show, pay no mind\") *\n\n                        Option(\"Do you think he's into pink ?\") *\n                            Hide() *\n                            Yell(redGuy, \"I heard that!\") *\n                            Show() *\n                            Write(0, \"... maybe we shouldnt talk about him anymore\") *\n\n                        Option(\"Back\") *\n                            Back() \n                    ) *\n\n                Option(\"Bye\") *\n                    Hide() *\n                    Yell(\"Bye bye!\") *\n                    End()\n            );\n\n    }\n}<\/pre>\n<h6><b>Code<\/b><\/h6>\n<p>This example shows that an Option can have an Options FluentNode as one of it&#8217;s children. Use Back( ) to instruct an Option to cause the dialogue to go back up the tree.<br \/> <a href=\"https:\/\/reyn.vlietstra.co.za\/wp-content\/uploads\/2015\/01\/branching.png\"><img decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-714 alignleft\" src=\"https:\/\/reyn.vlietstra.co.za\/wp-content\/uploads\/2015\/01\/branching.png\" alt=\"\" width=\"394\" height=\"416\" srcset=\"https:\/\/reyn.vlietstra.co.za\/wp-content\/uploads\/2015\/01\/branching.png 394w, https:\/\/reyn.vlietstra.co.za\/wp-content\/uploads\/2015\/01\/branching-284x300.png 284w, https:\/\/reyn.vlietstra.co.za\/wp-content\/uploads\/2015\/01\/branching-189x200.png 189w\" sizes=\"(max-width: 394px) 100vw, 394px\" \/><\/a><\/p>\n\n<\/div><h2 class=\"tabtitle\">7<\/h2>\n<div class=\"tabcontent\">\n\n<h3>7: Running Code<\/h3>\n<pre class=\"toolbar:1 lang:c# decode:true\">public class Conversation7 : MyFluentDialogue\n{\n    Color pink = new Color(1.0f, 0.412f, 0.706f);\n    Color blue = Color.blue;\n\n    private void PlayerColor(Color color)\n    {\n        Player.Instance.gameObject.GetComponentInChildren().color = color;\n    }\n\n    public override FluentNode Create()\n    {\n        return\n            Show() *\n            Write(0, \"Time to realise your choices affect the world!\") *\n\n            Options\n            (\n                Option(\"Make me pink!\") *\n                    Write(\"Abara Kadabara!\") *\n                    Do(() =&gt; PlayerColor(pink)) *\n\n                Option(\"Make me blue!\") *\n                    Hide() *\n                    Yell(\"Abara Kadabara!\") *\n                    Do(() =&gt; PlayerColor(blue)) *\n                    Pause(1) *\n                    Show() *\n\n                Option(\"Bye !\") *\n                    Hide() *\n                    Yell(\"Bye bye!\") *\n                    End()\n             );\n    }\n}<\/pre>\n<h6><b>Code<\/b><\/h6>\n<p>Here we introduce a new <strong>FluentNode<\/strong>. Do executes a delegate.<\/p>\n\n<\/div><h2 class=\"tabtitle\">8<\/h2>\n<div class=\"tabcontent\">\n\n<h3>8: VisibleIf<\/h3>\n<pre class=\"toolbar:1 lang:c# decode:true\">public class Conversation8 : MyFluentDialogue\n{\n    public GameObject player;\n    bool gotHorsey = false;\n\n    public override FluentNode Create()\n    {\n        return\n            Show() *\n            Write(0, \"Options can be shown or hidden based on code!\") *\n\n            Options\n            (\n                Option(\"I want a HORSEY!\").VisibleIf(() =&gt; !gotHorsey) *\n                    Write(\"Here you go!\") *\n                    Do(() =&gt; gotHorsey = true) *\n\n                Option(\"My horsey died! Give me another one!\").VisibleIf(() =&gt; gotHorsey) *\n                    Write(\"That was the only one in the world!\") *\n                    Hide() *\n                    Yell(player, \":(\") *\n                    Show() *\n\n                Option(\"Bye!\") *\n                    Hide() *\n                    Yell(\"Bye bye!\") *\n                    End()\n             );\n    }\n}<\/pre>\n<h6><b>Code<\/b><\/h6>\n<p>There is a method on Option called VisibleIf( ) which takes a delegate, if that delegate returns true then that option will be shown.<\/p>\n\n<\/div><h2 class=\"tabtitle\">9<\/h2>\n<div class=\"tabcontent\">\n\n<h3>9: Click Initiator<\/h3>\n<pre class=\"toolbar:1 lang:c# decode:true\">public class Conversation9 : MyFluentDialogue\n{\n    public override FluentNode Create()\n    {\n        return Yell(\"You clicked on me!\");\n    }\n}<\/pre>\n<h6><b>Code<\/b><\/h6>\n<p>By default <strong>FluentScript<\/strong> looks for a <strong>GameActionInitiator<\/strong>, if it doesn&#8217;t find one it automatically adds a <strong>ProximityInitiator<\/strong>. For clicking to work we add the ClickInitiator script to our object.<br \/> <a href=\"https:\/\/reyn.vlietstra.co.za\/wp-content\/uploads\/2015\/01\/clickinitiator.png\"><img decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-717 alignleft\" src=\"https:\/\/reyn.vlietstra.co.za\/wp-content\/uploads\/2015\/01\/clickinitiator.png\" alt=\"\" width=\"431\" height=\"237\" srcset=\"https:\/\/reyn.vlietstra.co.za\/wp-content\/uploads\/2015\/01\/clickinitiator.png 431w, https:\/\/reyn.vlietstra.co.za\/wp-content\/uploads\/2015\/01\/clickinitiator-300x165.png 300w, https:\/\/reyn.vlietstra.co.za\/wp-content\/uploads\/2015\/01\/clickinitiator-364x200.png 364w\" sizes=\"(max-width: 431px) 100vw, 431px\" \/><\/a><\/p>\n\n<\/div><h2 class=\"tabtitle\">10<\/h2>\n<div class=\"tabcontent\">\n\n<h3>10: Parallel Chains<\/h3>\n<pre class=\"toolbar:1 lang:c# decode:true\">public class Conversation10 : MyFluentDialogue\n{\n    FluentNode Speak(string text, string soundResource)\n    {\n        return Parallel\n            (\n                Write(text) *\n                Sound(soundResource)\n            );\n    }\n\n    public override FluentNode Create()\n    {\n        return \n            Show() *            \n            Options\n            (\n                Write(0, \"We can run multiple responses in parallel!\") *\n                Option(\"Make multiple responses happen at the same time!\") *\n                    Speak(\"Here is some text being printed, while a sound is being played!\", \"Sounds\/hello\") *\n\n                Option(\"Can I chain parallel nodes ?\") *\n                    Write(\"What follows is both sound and text that has to finish before the next sound and text can play\") *\n                    Speak(\"Yes\", \"Sounds\/yes\") *\n                    Speak(\"We can chain parallel responses\", \"Sounds\/chainparallel\") *\n\n                Option(\"Bye!\") *\n                    Hide() *\n                    Parallel\n                    (\n                        Yell(\"Bye bye!\") *\n                        Sound(\"Sounds\/byebye\")\n                    ) *\n                    End()\n            );\n    }\n}<\/pre>\n<h6><b>Code<\/b><\/h6>\n<p>Here we introduce a new <strong>FluentNode<\/strong>. Sound( ) will play an audio resource. There exist cases where we want multiple <strong>FluentNodes<\/strong> to execute at the same time. Playing sounds while text is being written is a good example. The nodes specified in a Parallel node will all execute at the same time. Parallel will only complete once all it&#8217;s parallel nodes have finished. Note here we created a helper method that combines writing and playing sound in one convenient method.<br \/><a href=\"https:\/\/reyn.vlietstra.co.za\/wp-content\/uploads\/2015\/01\/parallel.png\"><img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/reyn.vlietstra.co.za\/wp-content\/uploads\/2015\/01\/parallel.png\" alt=\"\" width=\"431\" height=\"434\" \/><\/a><\/p>\n\n<\/div><h2 class=\"tabtitle\">11<\/h2>\n<div class=\"tabcontent\">\n\n<h3>11: Only Once<\/h3>\n<pre class=\"toolbar:1 lang:c# decode:true\">public class Conversation11 : MyFluentDialogue\n{\n    public override FluentNode Create()\n    {\n        return\n            Show() *\n            Write(\"Only once responses will happen again when the conversation is restarted\") *\n            Options\n            (\n                Option(\"What is the secret message ?\") *\n                    Once\n                    (\n                        Write(\"OOOGABOOGA!\") \n                    ) *\n                    Write(\"Restart the conversation to hear the secret again\") *\n\n                Option(\"Bye!\") *\n                    Hide() *\n                    Yell(\"Bye bye!\") *\n                    End()\n            );\n    }\n}<\/pre>\n<h6><b>Code<\/b><\/h6>\n<p>Nodes within Once will only be executed once for the current conversation, but will happen again if the conversation is restarted.<\/p>\n\n<\/div><h2 class=\"tabtitle\">12<\/h2>\n<div class=\"tabcontent\">\n\n<h3>12: If<\/h3>\n<pre class=\"toolbar:1 lang:c# decode:true\">public class Conversation12 : MyFluentDialogue\n{\n    int timesVisited = 0;\n\n    public override FluentNode Create()\n    {\n        return\n            Do(() =&gt; timesVisited++) *\n\n            If(() =&gt; timesVisited == 1,\n                Yell(\"I havent seen you before\") *\n                Yell(\"Lets be friends!\") *\n                Yell(\"Talk to me again sometime\")\n            ) *\n\n            If(() =&gt; timesVisited == 2,\n                Yell(\"I'm going to count your visits!\")\n            ) *\n\n            If(() =&gt; timesVisited &gt;= 2,\n                Yell(\"Visit number \" + timesVisited));\n\n    }\n}<\/pre>\n<h6><b>Code<\/b><\/h6>\n<p>Here we introduce a new <strong>FluentNode<\/strong>. The\u00a0<strong>If<\/strong>\u00a0node takes a bool delegate as it\u2019s first parameter and a fluent chain as it\u2019s second. The fluent chain will be executed if the bool delegate returns true. It is important to note that the visited number string concatenation in this example is evaluated before the Do() response is executed. If you would like the string to be evaluated at execution time then you need to use Eval(( ) =&gt; &#8220;Visit number &#8221; + timesVisited)<\/p>\n\n<\/div><h2 class=\"tabtitle\">13<\/h2>\n<div class=\"tabcontent\">\n\n<h3>13: Multilingual<\/h3>\n<pre class=\"toolbar:1 lang:c# decode:true\">public class Conversation13 : MyFluentDialogue\n{\n    private void SetLanguage(Language language)\n    {\n        LanguageManager.CurrentLanguage = language;\n    }\n\n    public override void OnFinish()\n    {\n        LanguageManager.CurrentLanguage = Language.English;\n        base.OnFinish();\n    }\n\n    public override FluentNode Create()\n    {\n        return\n            Show() *\n            Write(0, speakManyLanguages) *\n            Options\n            (\n                Option().Text(switchToEnglish).VisibleIf(() =&gt; LanguageManager.CurrentLanguage != Language.English) *\n                    Do(() =&gt; SetLanguage(Language.English)) *\n\n                Option().Text(switchToChinese).VisibleIf(() =&gt; LanguageManager.CurrentLanguage != Language.Mandarin) *\n                    Do(() =&gt; SetLanguage(Language.Mandarin)) *\n\n                Option().Text(switchToAfrikaans).VisibleIf(() =&gt; LanguageManager.CurrentLanguage != Language.Afrikaans) *\n                    Do(() =&gt; SetLanguage(Language.Afrikaans)) *\n\n                Option().Text(singMeASong) *\n                    Write(singSong) *\n\n                Option().Text(bye) *\n                    Hide() *\n                    Yell(bye) *\n                    End()\n            );\n    }\n\n    object[] singSong = {\n                        Language.English, englishSong,\n                        Language.Afrikaans, afrikaansSong,\n                        Language.Mandarin, mandarinSong};\n    object[] speakManyLanguages = {\n                Language.English, \"I speak a couple of languages\",\n                Language.Afrikaans, \"Ek praat 'n paar tale\",\n                Language.Mandarin, \"\u6211\u8bb2\u51e0\u79cd\u8bed\u8a00\"};\n    object[] switchToEnglish = {\n                Language.Mandarin, \"\u6539\u7528\u666e\u901a\u8bdd (*)\",\n                Language.Afrikaans, \"Skuif na Engels (*)\"};\n    object[] switchToChinese = {\n                Language.English, \"Switch to Mandarin\",\n                Language.Afrikaans, \"Skuif na Shinees\"};\n    object[] switchToAfrikaans = {\n                Language.English, \"Switch to Afrikaans\",\n                Language.Mandarin, \"\u5207\u6362\u5230\u5357\u975e\u8377\u5170\u8bed\"};\n    object[] singMeASong = {\n                Language.English, \"Sing me a song!\",\n                Language.Afrikaans, \"Sing vir my 'n liedjie!\",\n                Language.Mandarin, \"\u5531\u6b4c\"};\n    object[] bye = {\n                Language.English, \"Bye\",\n                Language.Afrikaans, \"Totsiens\",\n                Language.Mandarin, \"\u518d\u89c1\"};\n\n    const string afrikaansSong =\n@\"Wielie, Wielie, Waalie!\nDie aap ry op sy baalie!\nTjoef tjaf val hy af\nWielie, Wielie, Waalie!\";\n\n    const string englishSong =\n@\"Ring-a-round the rosie,\nA pocket full of posies,\nAshes! Ashes!\nWe all fall down!\";\n\n    const string mandarinSong =\n@\"\u6211\u4eec \u662f \u5171\u4ea7\u4e3b\u4e49 \u63a5\u73ed\u4eba\n\u7ee7\u627f \u9769\u547d \u5148\u8f88 \u7684 \u5149\u8363 \u4f20\u7edf\n\u7231 \u7956\u56fd \u7231 \u4eba\u6c11\n\u9c9c\u8273 \u7684 \u7ea2\u9886\u5dfe \u98d8\u626c \u5728 \u524d\u80f8\";\n}<\/pre>\n<h6><b>Code<\/b><\/h6>\n\n<\/div><h2 class=\"tabtitle\">14<\/h2>\n<div class=\"tabcontent\">\n\n<h3>14: ContinueWhen<\/h3>\n<pre class=\"toolbar:1 lang:c# decode:true\">public class Conversation14 : MyFluentDialogue\n{\n    public GameObject blueGuy2;\n    public GameObject player;\n    public bool HasVisitedRed { get; set; }\n    bool cameBackForPrize { get; set; }    \n\n    public override void OnStart()\n    {\n        HasVisitedRed = false;\n        cameBackForPrize = false;\n    }\n\n    public override FluentNode Create()\n    {\n        return\n            Yell(\"Stand next to that red guy\") *\n            ContinueWhen(() =&gt; HasVisitedRed) *\n\n            Yell(blueGuy2, \"Well done!\") *\n            Yell(blueGuy2, \"Go back for your prize!\") *\n            ContinueWhen(() =&gt; cameBackForPrize) *\n\n            Yell(player, \"Prize please!\") *\n            Yell(\"It was stolen!\") *\n            Yell(player, \";-(\");\n    }\n\n    void OnTriggerEnter(Collider collider)\n    {\n        if (HasVisitedRed)\n            cameBackForPrize = true;\n    }\n\n}<\/pre>\n<pre class=\"toolbar:1 lang:c# decode:true\">using UnityEngine;\n\npublic class BlueGuy2 : MonoBehaviour\n{\n    public GameObject NPC14;\n\n    void OnTriggerEnter(Collider collider)\n    {\n        NPC14.GetComponentInChildren().HasVisitedRed = true;\n    }\n}<\/pre>\n<h6><b>Code<\/b><\/h6>\n<p>Here we introduce a new <strong>FluentNode<\/strong>. ContinueWhen polls the passed in delegate and continues down the fluent chain once the delegate return true.<\/p>\n\n<\/div><h2 class=\"tabtitle\">15<\/h2>\n<div class=\"tabcontent\">\n\n<h3>15: Custom Conversation<\/h3>\n<pre class=\"toolbar:1 lang:c# decode:true\">public class Conversation15 : ConversationWithImage\n{\n    public override FluentNode Create()\n    {\n        return\n        Show() *\n        Write(0,\n            \"I am Balrog-the-great!\\n\\n\" +\n            \"This is a custom conversation that lets you set an image in the editor which will be displayed by the options presenter\") *\n        Options\n        (\n            Option(\"Bye Balrog!\") *\n                Hide() *\n                Yell(\"The GREAT!\") *\n                End()\n        );\n    }\n}<\/pre>\n<pre class=\"toolbar:1 lang:c# decode:true\">using UnityEngine;\nusing UnityEngine.UI;\nusing Fluent;\n\npublic abstract class ConversationWithImage : MyFluentDialogue\n{\n    public Sprite CharacterHeadSprite;\n\n    public override void OnStart()\n    {\n        SetNPCHead();\n        base.OnStart();\n    }\n\n    private void SetNPCHead()\n    {\n        OptionsPresenter optionsPresenter = GetComponent();\n        Image image = optionsPresenter.DialogUI.transform.Find(\"NPCHeadImage\").GetComponent();\n        image.sprite = CharacterHeadSprite;\n    }\n}<\/pre>\n<h6><b>Code<\/b><\/h6>\n<p>Here we again extend FluentScript, this time by allowing us to set an image of our NPC in the editor.<\/p>\n\n<\/div><h2 class=\"tabtitle\">16<\/h2>\n<div class=\"tabcontent\">\n\n<h3>16: While<\/h3>\n<pre class=\"toolbar:1 lang:c# decode:true\">public class Conversation16 : MyFluentDialogue\n{\n    public int EnemyHealth = 10;\n    public GameObject PlayerGameObject;\n    bool stillFighting = true;\n\n    public override void OnStart()\n    {\n        EnemyHealth = 10;\n        stillFighting = true;\n        base.OnStart();\n    }\n\n    void DoDamage(int damage)\n    {\n        EnemyHealth -= damage;\n        if (EnemyHealth &lt;= 0)\n            stillFighting = false;\n    }\n\n    FluentNode AttackOption(string itemName, string yell, int damage)\n    {\n        return\n            Option(itemName) *\n            Hide() *\n            Yell(PlayerGameObject, yell) *\n            Yell(\"You delt \" + damage + \" damage\") *\n            Do(() =&gt; DoDamage(damage)) *\n            Yell(Eval(() =&gt; EnemyHealth + \" hp left\")) *\n            Show() *\n            If(() =&gt; EnemyHealth &lt;= 0,\n                Hide() *\n                Yell(\"I died!\") *\n                Yell(\"You win!\")\n            ) *\n            End();\n    }   \n\n    FluentNode SpellList()\n    {\n        return\n            Options\n            (\n                AttackOption(\"Magic Missile\", \"Missles away!\", 4) *\n                AttackOption(\"Fairy Fire\", \"Boom!\", 2) *\n                Option(\"Back\") *\n                    Back()\n            );\n    }\n\n    public override FluentNode Create()\n    {\n        return\n            Show() *\n            While(() =&gt; stillFighting,\n                Show() * \n                Options\n                (\n                    If(() =&gt; EnemyHealth &gt;= 10, Write(0, \"You will NEVER defeat me !!\")) *\n                    If(() =&gt; EnemyHealth &gt;= 6 &amp;&amp; EnemyHealth &lt; 10, Write(0, \"I'v been hurt!\")) *\n                    If(() =&gt; EnemyHealth &gt;= 2 &amp;&amp; EnemyHealth &lt; 6, Write(0, \"Awwwwwwww! Stop that!\")) *\n\n                    Option(\"Spells\") *\n                        Write(0, \"Choose a spell\") *\n                        SpellList() *\n\n                    AttackOption(\"Melee\", \"Hand 2 Hand!\", 2) *                        \n\n                    Option(\"Flee\") *\n                        Hide() *\n                        Yell(\"Coward!\") *\n                        Do(() =&gt; stillFighting = false) *\n                        End()\n                )\n            );\n    }\n}<\/pre>\n<h6><b>Code<\/b><\/h6>\n<p>While, like If, takes a delegate as the first parameter and a fluent chain as the second. In this example the conversation will continue until stillFighting is false.<\/p>\n<\/div><\/div>","protected":false},"excerpt":{"rendered":"<p>After the WebGL above loads, click on it. Use the W\/A\/S\/D keys to move E to initiate conversation Fluent Dialogue is a dialogue\u00a0conversation\u00a0framework for unity. Conversations are defined using a fluent api in code. The unity asset is available for free on the unity asset store here Features Speech bubbles Conversation trees Multilingual User definable [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"ub_ctt_via":""},"featured_image_src":null,"_links":{"self":[{"href":"https:\/\/reyn.vlietstra.co.za\/index.php?rest_route=\/wp\/v2\/pages\/248"}],"collection":[{"href":"https:\/\/reyn.vlietstra.co.za\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/reyn.vlietstra.co.za\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/reyn.vlietstra.co.za\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/reyn.vlietstra.co.za\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=248"}],"version-history":[{"count":313,"href":"https:\/\/reyn.vlietstra.co.za\/index.php?rest_route=\/wp\/v2\/pages\/248\/revisions"}],"predecessor-version":[{"id":1167,"href":"https:\/\/reyn.vlietstra.co.za\/index.php?rest_route=\/wp\/v2\/pages\/248\/revisions\/1167"}],"wp:attachment":[{"href":"https:\/\/reyn.vlietstra.co.za\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=248"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}