Page 2 of 3

Re: How to Continue Conversations

Posted: Sun Apr 07, 2019 4:22 pm
by Salja
I use master audio, there is a way to display the continue button when the audio has finished playing?

Re: How to Continue Conversations

Posted: Sun Apr 07, 2019 5:07 pm
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 2742 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;
    }
}

Re: How to Continue Conversations

Posted: Mon Apr 08, 2019 1:11 pm
by Escara
Brilliant and thorough FAQ, Tony!

Re: How to Continue Conversations

Posted: Thu Sep 24, 2020 1:14 pm
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?

Re: How to Continue Conversations

Posted: Thu Sep 24, 2020 1:42 pm
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.

Re: How to Continue Conversations

Posted: Mon Mar 01, 2021 1:17 pm
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.

Re: How to Continue Conversations

Posted: Mon Mar 01, 2021 1:23 pm
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");

Re: How to Continue Conversations

Posted: Mon Mar 01, 2021 2:02 pm
by vcesauron
Works great. Thanks, Tony!

Re: How to Continue Conversations

Posted: Mon Mar 01, 2021 2:05 pm
by Tony Li
Happy to help!

Re: How to Continue Conversations

Posted: Thu Oct 06, 2022 11:59 am
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()).