Go to two nodes simultaneously/run them in parallel?

Announcements, support questions, and discussion for the Dialogue System.
Post Reply
chadblimey
Posts: 4
Joined: Tue Oct 01, 2024 4:07 pm

Go to two nodes simultaneously/run them in parallel?

Post by chadblimey »

Hi there, first off, thanks for such an amazing tool!
Just to preface, we've been sort of using the tool as a visual hierarchy in our game to dictate game flow + audio (although i'm not really sure if the game flow part is the intended use of the tool lol, hence the question).

As you can see in the screenshot below, we have a node called

Code: Select all

bella_c02_s01_i02
and its current Sequence is

Code: Select all

FMODWait(gfd,event:/Dialogs/Chapter 2/2.1/Bella/bella_c02_s01_i02);
which simply plays the FMOD event that we want. Now this works wonderfully, however this next part we're unsure if/how we can make it work. To the right of that node, we have a

Code: Select all

OnStart40Seconds
and below it we have

Code: Select all

OnHolocallRequest
. Simply put, can we make it such that we can run two nodes at the same time? Or is there some sort of custom sequence we'll have to create?



This is our intention:

1) bella_c02_s01_i02 plays then finishes
2a) We go to the OnStart40Seconds node that starts a timer/delay/etc in which after 40 seconds, another fmod audio event will play
2b) We also go to OnHolocallRequest where a notification pops up via Scene Event.

At the moment, we can do it such that it works linearly,(bella -> OnStart40Seconds -> OnHolocallRequest) however a problem that occurs for us is that let's say for example we add a delay to the FMODWait Sequence of 40 seconds, that means we can't reach the next part of our nodes (in this case OnHoloCallRequest) until the delay is complete.

Please let me know if that makes sense/there's something we can do in this scenario, thank you!
User avatar
Tony Li
Posts: 22145
Joined: Thu Jul 18, 2013 1:27 pm

Re: Go to two nodes simultaneously/run them in parallel?

Post by Tony Li »

Hi,

A conversation can only be in one node at a time.

I recommend getting rid of the OnStart40Seconds node. Instead, write a custom sequencer command to use in OnHolocallRequest's Sequence that kicks off the FMOD event after 40 seconds.
chadblimey
Posts: 4
Joined: Tue Oct 01, 2024 4:07 pm

Re: Go to two nodes simultaneously/run them in parallel?

Post by chadblimey »

@
Tony Li wrote: Tue Oct 01, 2024 5:16 pm
A conversation can only be in one node at a time.

I recommend getting rid of the OnStart40Seconds node. Instead, write a custom sequencer command to use in OnHolocallRequest's Sequence that kicks off the FMOD event after 40 seconds.
Thanks for the reply!

Following your advice, here's the custom sequencer command that we're playing.

Code: Select all

using FMODUnity;
using PixelCrushers.DialogueSystem.SequencerCommands;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SequencerCommandPlayAudio : SequencerCommand
{
    // This dictionary will store event names mapped to their paths
    private Dictionary<string, string> eventDictionary = new Dictionary<string, string>();

    public void Awake()
    {
        if (string.IsNullOrEmpty(GetParameter(0)) || string.IsNullOrEmpty(GetParameter(1)))
        {
            Debug.LogError("Use PlayCharacterSequence with a valid trigger.");
            Stop();
            return;
        }
        else
        {
            LoadAllFMODPaths();
            float delay = 0;
            string fmodEvent = "";
            float fmodDelay = 0;
            if (!string.IsNullOrEmpty(GetParameter(0)))
            {
                fmodEvent = GetParameter(0);
            }
            if (!string.IsNullOrEmpty(GetParameter(1)))
            {
                fmodDelay = float.Parse(GetParameter(1));
            }
            //Play character sequence with delay                
            StartCoroutine(PlayAudioWithDelay(fmodEvent, fmodDelay));
        }
    }


    private IEnumerator PlayAudioWithDelay(string eventName,float audioDelay)
    {
        yield return new WaitForSeconds(audioDelay);
        PlayEvent(GetEventPathByName(eventName));
        Stop();//comman is done playing, but still wait for the delay to play
    }
    
    // This function loads all the FMOD event paths and stores them in a dictionary
    private void LoadAllFMODPaths()
    {
        var eventDescriptions = new List<EventReference>();

        // Loop over all banks to get the event descriptions
        RuntimeManager.StudioSystem.getBankList(out FMOD.Studio.Bank[] banks);

        foreach (FMOD.Studio.Bank bank in banks)
        {
            bank.getEventList(out FMOD.Studio.EventDescription[] events);

            foreach (var eventDescription in events)
            {
                eventDescription.getPath(out string path);
                eventDictionary[System.IO.Path.GetFileNameWithoutExtension(path)] = path; // Store by event name
            }
        }
    }

    // This function returns the event path when given the event name
    public string GetEventPathByName(string eventName)
    {
        if (eventName == "") return "";

        if (eventDictionary.TryGetValue(eventName, out string path))
        {
            return path; // Return the event path if found
        }
        else
        {
            Debug.LogError("FMOD Event not found: " + eventName);
            return null;
        }
    }
    public void PlayEvent(string eventName)
    {
        if (eventName == "") return;

        // If the event path is found
        if (!string.IsNullOrEmpty(eventName))
        {
            // Play the event as a one-shot sound (useful for simple sound effects)
            FMODUnity.RuntimeManager.PlayOneShot(eventName);
        }
        else
        {
            Debug.LogError("FMOD Event not found for name: " + eventName);
        }
    }
}
I think our biggest question is when would you call the

Code: Select all

Stop
function? So if we get rid of the 40seconds node, then add this sequence onto the OnHolocallRequest node, we still want to add more nodes after OnHolocallRequest, but make sure that the 40 seconds still goes on and plays! We currently call Stop after the coroutine PlayAudioWithDelay. But I think in this instance, it will wait 40 seconds before it moves onto the next node and that isn't our intent.

Thank you :)
User avatar
Tony Li
Posts: 22145
Joined: Thu Jul 18, 2013 1:27 pm

Re: Go to two nodes simultaneously/run them in parallel?

Post by Tony Li »

Hi,

It depends.

If you want to always play the FMOD event after exactly 40 seconds even if the player advances past this dialogue entry before 40 seconds have elapsed, I recommend kicking off an independent process in Awake() and immediately calling Stop(). Use a different script to for the independent process. Example (simplified for readability):

Code: Select all

public class SequencerCommandPlayAudio : SequencerCommand
{
    public void Awake()
    {
        var fmodEvent = GetParameter(0);
        var fmodDelay = GetParameterAsFloat(1);
        AudioScheduler.ScheduleAudio(fmodEvent, fmodDelay);
        Stop();
    }
}
If you want to play the FMOD event early if the player advances the conversation before 40 seconds have elapsed:

Code: Select all

public class SequencerCommandPlayAudio : SequencerCommand
{
    private string fmodEvent;
    private bool hasPlayed;
    public void Awake()
    {
        fmodEvent = GetParameter(0);
        fmodDelay = GetParameterAsFloat(1);
        hasPlayed = false;
        Invoke(nameof(PlayEvent), fmodDelay);
    }
    
    void PlayEvent()
    {
        FMODUnity.RuntimeManager.PlayOneShot(fmodEvent);
        hasPlayed = true;
        Stop();
    }
    
    void OnDestroy()
    {
        if (!hasPlayed) FMODUnity.RuntimeManager.PlayOneShot(fmodEvent);
    }
}
Post Reply