Page 1 of 1

Execute script after/before conversation node

Posted: Thu Jun 02, 2016 10:33 pm
by sazr
Hi

What is the methodology to call a script during a conversation? For example (inside the Conversation Node editor); I have a Conversation node (CN) where the AI says "Hi", this CN links to another CN where the player selects "Hello" but before this happens my script executes that draws a moving GUI circle on screen.

I have my script all ready but how do I make the script execute after the AI says "Hi"? My script is in C# not lua though, will that still work?

Re: Execute script after/before conversation node

Posted: Thu Jun 02, 2016 10:46 pm
by Tony Li
Hi,

There are a few ways:

1. Register your C# method as a Lua function and then call it in the Script field of the dialogue entry node (aka conversation node). This is a very powerful feature. You can also use Lua functions in the Conditions field to determine which branches of the conversation the Dialogue System will follow, and you can use the [lua(code)] markup tag in your Dialogue Text and Menu Text to add dynamic text.

2. Or, write a custom sequencer command (they're actually quite easy to write) and call it in the Sequence field.

3. Or, if you want to do something on every dialogue entry node, add an OnConversationLine method to a script on the Dialogue Manager or one of the conversation participants.

Re: Execute script after/before conversation node

Posted: Fri Jun 03, 2016 1:02 am
by sazr
Hi, thanks for your quick reply. I went down the 'C# method as a lua function' and it works well. There's one last thing to do which is pause/block the conversation and show a circle image on the Dialogue UI which is not quite working.

For example; I have 3 conversation nodes 'Convo1', 'Combat1' and 'Convo2' when 'Combat1' runs I call my C# method and want to block/pause the conversation while a circular GUI/Image appears on the Dialogue UI and moves randomly for 3 seconds. Then we go to the next conversation node 'Convo2'.

Image

Code: Select all

public class DialogueListener : MonoBehaviour
{

    void Start()
    {
        DialogueManager.AddLuaObserver("Variable['Action']", LuaWatchFrequency.EveryDialogueEntry, OnActionChanged);
    }

    void OnActionChanged(LuaWatchItem luaWatchItem, Lua.Result newValue)
    {
        // How to 'pause' the conversation and stop it going to the next conversation node WHILST still being able to paint to the DialogueUI?
        DialogueManager.Pause();

        if (newValue.AsString == "ShowMovingCircleImage")
        {
            // For 5 seconds show GUI label or image and move it randomly around the 2d UI

            // ...will the DialogueManager.DialogueUI repaint/update if the DialogManager is paused?
        }


        DialogueManager.Unpause();
    }
}

Re: Execute script after/before conversation node

Posted: Fri Jun 03, 2016 10:36 am
by Tony Li
Hi,

DialogueManager.Pause pauses everything.

Instead, I recommend using a sequence for this. In general, the idea behind Lua (Script and Conditions fields) is to manage data such as variable values, and the idea behind sequences (Sequence field) is to control what the player sees and hears such as camera work and animation. The things that Lua and sequences do can overlap -- for example, you're free to do something visual in Lua, or set a variable in a sequencer command -- but this is the way I like to look at them.

Since this seems to be more of a user experience thing, here's how I would implement it:

1. Write a custom sequencer command called something like "ShowCustom":

Code: Select all

using UnityEngine;
using PixelCrushers.DialogueSystem;
 
namespace PixelCrushers.DialogueSystem.SequencerCommands
{

    // Command: ShowCustom(action)
    public class SequencerCommandShowCustom : SequencerCommand {
 
        public IEnumerator Start() {
            if (GetParameter(0) == "ShowMovingCircleImage")
            {
                float elapsedTime = 0;
                while (elapsedTime < 5)
                {
                    // Show your circle image, etc.    
                    elapsedTime += Time.deltaTime;
                    yield return null;
                }            
            }
            Stop();
        }
    }
}
2. Use it in the dialogue entry node's Sequence field:
  • Sequence: ShowCustom(ShowMovingCircleImage)
A dialogue entry node waits until its sequence completes. If you pass this command "ShowMovingCircleImage", it does something for 5 seconds and then completes. This means the dialogue entry node will stay onscreen for 5 seconds. Note when you pass strings to sequencer commands, you don't wrap them in quotes. The syntax for sequencer commands was designed for non-technical authors, so it's ultra-simplified.


---
Alternate Method:

If you want to stick with Lua, here's an alternate method:

1. Use the "@Message" syntax to set the dialogue entry node's Sequence field to:
  • Sequence: None()@Message(Done)
The None() sequencer command is a null command. However, because of the "@Message(Done)" at the end, it will wait until it receives a sequencer message "Done". This means the dialogue entry node will stay onscreen until it receives the "Done" message.

2. Set the Script field to something like this:
  • Script: CustomShowMethod("ShowMovingCircleImage")
3. Change your script to something like this:

Code: Select all

public class DialogueListener : MonoBehaviour
{

    void OnEnable() {
        Lua.RegisterFunction("CustomShowMethod", this, typeof(DialogueListener).GetMethod("CustomShowMethod"));
    }
        
    void OnDisable() {
        Lua.UnregisterFunction("CustomShowMethod");
    }
    
    void CustomShowMethod(string action) 
    {
        if (action == "ShowMovingCircleImage")
        {
            StartCoroutine(ShowMovingCircleImage());
        }
    }
    
    IEnumerator ShowMovingCircleImage()
    {
        float elapsedTime = 0;
        while (elapsedTime < 5)
        {
            elapsedTime += Time.deltaTime;
            // Show your circle image, etc.    
        }
        Sequencer.Message("Done");
    }
}