Page 1 of 1

Let external narrative tool decide bark or conversation

Posted: Tue Oct 04, 2022 9:20 am
by leonfor
Hi Tony,

our designers requested a rather neat feature: we're using Articy for our project, and we're currently triggering barks and conversations "statically" from Unity. By "statically" I mean that Unity knows that triggers, for example, will only ever trigger barks and not dialogues.

This works but it means that designers can't choose from inside Articy whether the content to be served is a bark or a dialogue based on the narrative state of the game in that moment.

Also, we're using a single entry point architecture for our Unity-Articy pipeline. Basically, Unity only ever starts conversations or barks from a single root dialogue entry from which the traversal starts and eventually arrives at the right entry based on game state.

We thought about marking a single dialogue fragment as either bark or dialogue, and that is easily done by assigning a field, but the real issue is that there seems to be no way of traversing the nodes without actually starting a conversation or barking. So my question is: can we "poll" the database, as if starting a conversation, but without actually starting it and instead reading fields from the selected dialogue entry where the traversal lands?

I hope I've made the issue clear, I am at your disposal for any questions.

Thanks as always for the excellent support.
Cheers,
LF

Re: Let external narrative tool decide bark or conversation

Posted: Tue Oct 04, 2022 10:12 am
by Tony Li
Hi Leon,

Yes, you can traverse the nodes without starting a conversation. Create a ConversationModel object and check the firstState property's responses. The firstState property will be the equivalent of the <START> node in the Dialogue Editor, so you'll want to look at what it links to.

Once you know which Response.destinationEntry to show, I recommend using its conversation ID and entry ID to start the conversation directly from that entry ID instead of re-traversing the entire thing again when starting the conversation.

There are some edge cases where the articy importer creates empty nodes that auto-continue without showing subtitles. If you hit any of those cases, you may need to do a little extra traversal to get to the actual node, or maybe just start at that auto-continue node.

Re: Let external narrative tool decide bark or conversation

Posted: Tue Oct 04, 2022 11:05 am
by leonfor
Hi again,

this solution doesn't seem to achieve what we had in mind. I tried to create an instance of ConversationModel and it was a little weird because all the properties of firstState were empty, null or false except for "subtitle" which contained the dialogueEntry with all the data of the first node in the tree after START.

Aside from that, the real problem is that, if I understand correctly, you suggest traversing the nodes "manually"? Like actually iterating through all the links while evaluating all the conditions (and executing all the instructions found along the way, which might be a problematic behaviour coming to think of it..) until the first dialogue node is found, checking the isDialogue field and then starting either a conversation or a bark from there; did I get that right?

But I couldn't find any "Evaluate()" function on a DialogueEntry so I can't figure out how to traverse manually. Or maybe there's a way through the API to get straight to the first evaluated dialogue entry (like we originally imagined)?

Thank you and sorry for any incomprehensions,
LF

Re: Let external narrative tool decide bark or conversation

Posted: Tue Oct 04, 2022 2:53 pm
by Tony Li
Hi Leon,

Here's an example:

DS_TestConversationModel_2022-10-04.unitypackage

It uses this script:
TestConversationModel.cs

Code: Select all

using UnityEngine;
using PixelCrushers.DialogueSystem;

public class TestConversationModel : MonoBehaviour
{
    [ConversationPopup] public string entrypointConversation;

    private void Start()
    {
        var model = new ConversationModel(DialogueManager.masterDatabase, entrypointConversation, null, null, false, null);
        if (model.firstState.hasNPCResponse)
        {
            var nextState = model.GetState(model.firstState.firstNPCResponse.destinationEntry);
            var entry = nextState.subtitle.dialogueEntry;
            Debug.Log($"NPC line [{entry.conversationID}:{entry.id}]: '{nextState.subtitle.formattedText.text}'");
        }
        else if (model.firstState.hasPCResponses)
        {
            var nextState = model.GetState(model.firstState.pcResponses[0].destinationEntry);
            var entry = nextState.subtitle.dialogueEntry;
            Debug.Log($"Player line [{entry.conversationID}:{entry.id}]: '{nextState.subtitle.formattedText.text}'");
        }
        else
        {
            Debug.Log("No valid line.");
        }
    }
}
The test scene starts conversation "Entrypoint Conversation" that links to conversations A and B. The Conditions on A's text node is false, so it should report "Line B" in the Console window when you play the scene.

(My comment about manually processing some subtrees regards an edge case where a dialogue entry has blank text and its Sequence is set to "Continue()". This kind of dialogue entry is skipped in the dialogue UI, but the script above won't skip it. I'm not sure you'll ever have a dialogue entry like that. If you do, I can explain how to skip past that node. There's no DialogueEntry.Evaluate(). Instead, you'll call ConversationModel.GetState() to get the state of the next dialogue entry after that one.)

Re: Let external narrative tool decide bark or conversation

Posted: Wed Oct 05, 2022 5:22 am
by leonfor
Hi Tony,

I'm happy to tell you that this works perfectly! Now I get what you meant in the first post reply.

Just a couple of notes:
  • we noticed there's no equivalent of StartConversation(conversationTitle, actor, conversant, startingEntryID) for barks; would be nice to have so as to not repeat a portion of the traversal already done when calculating which node to serve;
  • yes, we have a few of those Continue() nodes here and there, created by the Articy importer; could you please explain how to skip past those?

Thank you so much, this will be a game changer!

Re: Let external narrative tool decide bark or conversation

Posted: Wed Oct 05, 2022 8:40 am
by Tony Li
Hi,

For barks, since you already have the conversation state, you can use DialogueManager.BarkString() to bark it. No need to tell it to grab the conversation again and look up the dialogue entry.

To bypass "Continue()", modify the script like this:

DS_TestConversationModel_2022-10-05.unitypackage
Spoiler

Code: Select all

using UnityEngine;
using PixelCrushers.DialogueSystem;

public class TestConversationModel : MonoBehaviour
{
    [ConversationPopup] public string entrypointConversation;

    private void Start()
    {
        var model = new ConversationModel(DialogueManager.masterDatabase, entrypointConversation, null, null, false, null);
        var state = BypassEmptyNodes(model, model.GetState(GetFirstResponseEntry(model.firstState)));
        if (state != null)
        {
            var entry = state.subtitle.dialogueEntry;
            Debug.Log($"Line [{entry.conversationID}:{entry.id}]: '{state.subtitle.formattedText.text}'");
        }
        else
        {
            Debug.Log("No valid line.");
        }
    }

    private DialogueEntry GetFirstResponseEntry(ConversationState state)
    {
        return (state == null) ? null
            : state.hasNPCResponse ? state.firstNPCResponse.destinationEntry
            : state.hasPCResponses ? state.pcResponses[0].destinationEntry
            : null;
    }

    private ConversationState BypassEmptyNodes(ConversationModel model, ConversationState state)
    {
        if (state == null) return null;
        if (string.Equals(state.subtitle.sequence, "Continue()"))
        {
            return BypassEmptyNodes(model, model.GetState(GetFirstResponseEntry(state)));
        }
        else
        {
            return state;
        }
    }
}
Note: This example script uses recursion. You might want to pass along a "depth" value that you increment every time you recursively call BypassEmptyNode(). If the depth value gets past a threshold (e.g., maybe 100), fail out by returning null. This will it won't get into an infinite loop if you've created a loop of Continue() nodes in your dialogue database.

Re: Let external narrative tool decide bark or conversation

Posted: Fri Oct 14, 2022 11:59 am
by leonfor
Hi Tony,

sorry for the delay, but I wanted to test the solution thoroughly before posting a reply.

Everything is working properly and it's simply amazing.

Thank you so much again,
LF

Re: Let external narrative tool decide bark or conversation

Posted: Fri Oct 14, 2022 1:07 pm
by Tony Li
Happy to help! I'm glad it's working the way you want.