How to Continue Conversations

Announcements, support questions, and discussion for the Dialogue System.
Salja
Posts: 1
Joined: Sun Apr 07, 2019 4:19 pm

Re: How to Continue Conversations

Post by Salja »

I use master audio, there is a way to display the continue button when the audio has finished playing?
User avatar
Tony Li
Posts: 21069
Joined: Thu Jul 18, 2013 1:27 pm

Re: How to Continue Conversations

Post by Tony Li »

Yes. You'll use a short script.

Assuming you're using a PlaylistController to play audio (e.g., the Dialogue System's MAPlaylistClip() sequencer command), on the MasterAudio GameObject define a custom event named, for example, "SongEnded".

On the PlaylistController GameObject, configure the Song Ended Event to call the SongEnded event:
maContinue1.png
maContinue1.png (36.36 KiB) Viewed 2573 times
Add an ICustomEventReceiver script to the Dialogue Manager that handles the SongEnded event. Something like the script below. This script hides the continue button, waits until Master Audio sends a SongEnded event, and then shows the continue button.
HideContinueButtonUntilSongEnds.cs

Code: Select all

using UnityEngine;
using PixelCrushers.DialogueSystem;
using DarkTonic.MasterAudio;
using System.Collections;

public class HideContinueButtonUntilSongEnds : MonoBehaviour, ICustomEventReceiver 
{
    private bool songEnded;
    
    // Dialogue System calls this method just before showing a subtitle:
    void OnConversationLine(Subtitle subtitle)
    {
        StartCoroutine(MonitorSong(subtitle)); // Start coroutine to handle continue button.
    }
    
    IEnumerator MonitorSong(Subtitle subtitle)
    {
        songEnded = false;
        var ui = DialogueManager.dialogueUI as AbstractDialogueUI;
        yield return new WaitForEndOfFrame(); // Let dialogue UI set up subtitle.
        ui.HideContinueButton(subtitle); // Hide continue button until song ends.
        while (!songEnded) { yield return null; } // Wait for song to end.
        ui.ShowContinueButton(subtitle); // Song ended, so show continue button.
    }

    // Methods to satisfy ICustomEventReceiver:    
    void OnEnable() { RegisterReceiver(); }
    void OnDisable() { if (MasterAudio.SafeInstance == null || MasterAudio.AppIsShuttingDown) return; else UnregisterReceiver(); }

    public void ReceiveEvent(string customEventName, Vector3 originPoint) {
        if (customEventName == "SongEnded") songEnded = true;
    }

    public bool SubscribesToEvent(string customEventName) {
        return string.IsNullOrEmpty(customEventName)) ? false : _eventsSubscribedTo.Contains(customEventName);
    }

    public void RegisterReceiver() {
        MasterAudio.AddCustomEventReceiver(this, transform);
    }

    public void UnregisterReceiver() {
        MasterAudio.RemoveCustomEventReceiver(this);
    }

    public IList<AudioEventGroup> GetAllEvents() {
        var events = new List<AudioEventGroup>();
        for (var i = 0; i < _eventsSubscribedTo.Count; i++) {
            events.Add(new AudioEventGroup {
                customEventName = _eventsSubscribedTo[i]
            });
        }
        return events;
    }
}

Another way to do this is to send a sequencer message when the song ends. Then you can do most of the work inside the Sequence instead of the script. For example, the Sequence could be:

Code: Select all

SetContinueMode(false);
MAPlaylistClip(entrytag);
required SetContinueMode(true)@Message(SongEnded);
The advantage of this is that you can have some nodes that don't play Master Audio clips. The script would be:
SequencerMessageWhenSongEnds.cs

Code: Select all

using UnityEngine;
using PixelCrushers.DialogueSystem;
using DarkTonic.MasterAudio;
using System.Collections;

public class SequencerMessageWhenSongEnds : MonoBehaviour, ICustomEventReceiver 
{
    void OnEnable() { RegisterReceiver(); }
    void OnDisable() { if (MasterAudio.SafeInstance == null || MasterAudio.AppIsShuttingDown) return; else UnregisterReceiver(); }

    public void ReceiveEvent(string customEventName, Vector3 originPoint) {
        if (customEventName == "SongEnded") Sequencer.Message("SongEnded");
    }

    public bool SubscribesToEvent(string customEventName) {
        return string.IsNullOrEmpty(customEventName)) ? false : _eventsSubscribedTo.Contains(customEventName);
    }

    public void RegisterReceiver() {
        MasterAudio.AddCustomEventReceiver(this, transform);
    }

    public void UnregisterReceiver() {
        MasterAudio.RemoveCustomEventReceiver(this);
    }

    public IList<AudioEventGroup> GetAllEvents() {
        var events = new List<AudioEventGroup>();
        for (var i = 0; i < _eventsSubscribedTo.Count; i++) {
            events.Add(new AudioEventGroup {
                customEventName = _eventsSubscribedTo[i]
            });
        }
        return events;
    }
}
Escara
Posts: 78
Joined: Sun Dec 30, 2018 4:55 am

Re: How to Continue Conversations

Post by Escara »

Brilliant and thorough FAQ, Tony!
Strig
Posts: 40
Joined: Fri Aug 21, 2020 12:33 pm

Re: How to Continue Conversations

Post by Strig »

Hello, Tony! Nice FAQ thread!

In my Dialogue Manager, I have set the key that starts the conversation as the same one that continues it, for the sake of consistency. Like one would use the "A" button as a general "confirm" in a dialogue.

Thing is: when I press the button to continue, the system gives me an alert becuse it's "unable to start a conversation" due to one already being active. And this happens every single time I press the key to continue.

Out of curiosity: can I stop this check altogether? Would it help with efficiency? Or should I just disable alerts in the Dialogue Manager?
User avatar
Tony Li
Posts: 21069
Joined: Thu Jul 18, 2013 1:27 pm

Re: How to Continue Conversations

Post by Tony Li »

Hi,

Use a Dialogue System Events component to disable whatever component listens for "A" to start the conversation. For example, in DemoScene1 the Player GameObject has a Dialogue System Events component whose OnConversationStart() event disables the Selector. The OnConversationEnd() event re-enables it.
User avatar
vcesauron
Posts: 17
Joined: Tue Oct 06, 2020 11:22 am

Re: How to Continue Conversations

Post by vcesauron »

Hi Tony.

How do I hide the Continue Button from inside the dialogue tree, temporarily? Given that my Continue Button Mode is set to Always.

I'm making a node invoke a separate window via the Script field, and I wanted the dialogue tree to wait for the result of that window (through user input). So I want to prevent the player from accidentally advancing the dialogue by disabling/hiding the Continue button.
I tried SetContinueMode(false) on the Sequence field. It hides the button, but it causes the dialogue to advance automatically.
I also tried to disable the Continue Button gameObject via C# when the window is enabled, but the button is apparently reactivated right after, because of other stuff.
User avatar
Tony Li
Posts: 21069
Joined: Thu Jul 18, 2013 1:27 pm

Re: How to Continue Conversations

Post by Tony Li »

Hi,

Try setting the Sequence field to something like this:

Code: Select all

SetContinueMode(false);
WaitForMessage(SeparateWindowClosed)
This will keep the sequence active (and thus the conversation stopped at that dialogue entry node) until the sequencer receives the message string "SeparateWindowClosed".

When the other window closes, use a line of C# code to send that message:

Code: Select all

Sequencer.Message("SeparateWindowClosed");
User avatar
vcesauron
Posts: 17
Joined: Tue Oct 06, 2020 11:22 am

Re: How to Continue Conversations

Post by vcesauron »

Works great. Thanks, Tony!
User avatar
Tony Li
Posts: 21069
Joined: Thu Jul 18, 2013 1:27 pm

Re: How to Continue Conversations

Post by Tony Li »

Happy to help!
yurijh
Posts: 13
Joined: Thu Oct 06, 2022 6:49 am

Re: How to Continue Conversations

Post by yurijh »

Hi,
is there a cleaner way to trigger the Continue function through touch? I don't like the giant transparent button very much :D
It would be very appreciated a method just as StartConversation() (ex. Continue()).
Post Reply