Help with Repeatable Conversation and Node Tracking

Announcements, support questions, and discussion for the Dialogue System.
caltaylor101
Posts: 7
Joined: Mon Nov 11, 2024 7:20 pm

Help with Repeatable Conversation and Node Tracking

Post by caltaylor101 »

Hello,

I am trying to set up a dialogue system in Unity where the player can have repeatable conversations with multiple choice options, and return to specific points within the conversation. I’d like to be able to:

Start in Conversation 1, where the player makes choices.
Hit a point in Conversation 1 where it can pause and be resumed later.
Switch to Conversation 2, make choices there.
Return to the exact spot they left in Conversation 1.
Decide whether to continue Conversation 2 or take other actions.
Here’s an example workflow:

Conversation 1 ➔ Player makes choices ➔ Reaches a node to pause ➔ Saves position in Conversation 1.
Conversation 2 ➔ Player makes choices ➔ Returns to saved position in Conversation 1.
Repeats as needed.
Current Code

I found some code from another post that mostly achieves what I want, but it’s not perfect. Here’s what I have so far:

Code: Select all

private string _lastConversationStarted;
private int _lastConversationID; 

public void SwitchToConversationAction(string conversation)
{
    _lastConversationStarted = DialogueManager.lastConversationStarted;
    _lastConversationID = DialogueManager.currentConversationState.subtitle.dialogueEntry.id;

    DialogueManager.StopConversation();
    DialogueManager.StartConversation(conversation);
}

public void ContinueConversation()
{
    DialogueManager.StopConversation(); 
    DialogueManager.StartConversation(_lastConversationStarted, null, null, _lastConversationID);
}

Problem:

The main issue is that when I attempt to switch back to a previously paused conversation, it does not return to the correct node. Here’s the workflow I’m experiencing:

SwitchToConversationAction from Conversation A ➔ Go to Conversation B ➔ Return to saved node in Conversation A with ContinueConversation.
SwitchToConversationAction again from Conversation A ➔ Go to Conversation B ➔ Attempt to return to Conversation A, but this time it resumes at the wrong node.

Does anyone have any suggestions on how I can resolve this? Is there another property I should be using instead?

Thank you in advance!
User avatar
Tony Li
Posts: 22104
Joined: Thu Jul 18, 2013 1:27 pm

Re: Help with Repeatable Conversation and Node Tracking

Post by Tony Li »

Hi,

If I understand correctly, you can do this without any programming. Here's an example Conversation 1:

checkpointConversation.png
checkpointConversation.png (32.76 KiB) Viewed 261 times

The <START> node links to two nodes.

Let's look at the rightmost node first. It's used the first time the player talks to the NPC. The "Nice to meet you" line sets a Dialogue System variable (e.g., Variable["MetNPC"] = true). The player can then choose to end the conversation ("I have to go") or continue the conversation.

Now let's look at the leftmost node. It has Conditions that check if the variable is set (e.g., Variable["MetNPC"] == true). The next time the player starts Conversation 1, the conversation will go down this branch. The NPC will say "Good to see you again," and the conversation will continue at the "checkpoint" instead of the very beginning.
caltaylor101
Posts: 7
Joined: Mon Nov 11, 2024 7:20 pm

Re: Help with Repeatable Conversation and Node Tracking

Post by caltaylor101 »

Hello, thanks for your help! I think my goal might be a little different than what you described.

What I’m aiming for is to keep Conversation B as a standalone sequence that can be used across different contexts. Conversation B would act as a reusable “action dialogue” that could be triggered at various points within other conversations.

Ideally, I’d like a way to start Conversation B from within any other conversation, have a sequence of actions play out in Conversation B, and then automatically return to the exact point in the original conversation where it was triggered once Conversation B finishes. This way, I can incorporate Conversation B into multiple conversations without needing to duplicate it or modify each time.

Conversation A.png
Conversation A.png (60.74 KiB) Viewed 259 times
So in this mock example, I want to save the circled node.
Then if the player fights, they are taken to Conversation B, where there is a repeatable format I can reuse and inject anywhere else.

When Conversation B ends, it ideally goes to that circled node in Conversation A.
And later on, another node in that conversation.


Does that make sense? Thanks again for your help!
caltaylor101
Posts: 7
Joined: Mon Nov 11, 2024 7:20 pm

Re: Help with Repeatable Conversation and Node Tracking

Post by caltaylor101 »

Hello, thanks for your help! I think my goal might be a little different than what you described.

What I’m aiming for is to keep Conversation B as a standalone sequence that can be used across different contexts. Conversation B would act as a reusable “action dialogue” that could be triggered at various points within other conversations.

Ideally, I’d like a way to start Conversation B from within any other conversation, have a sequence of actions play out in Conversation B, and then automatically return to the exact point in the original conversation where it was triggered once Conversation B finishes. This way, I can incorporate Conversation B into multiple conversations without needing to duplicate it or modify each time.

Conversation A.png
So in this mock example, I want to save the circled node.
Then if the player fights, they are taken to Conversation B, where there is a repeatable format I can reuse and inject anywhere else.

When Conversation B ends, it ideally goes to that circled node in Conversation A.
And later on, another node in that conversation.


Does that make sense? Thanks again for your help!
Last edited by caltaylor101 on Mon Nov 11, 2024 9:09 pm, edited 1 time in total.
caltaylor101
Posts: 7
Joined: Mon Nov 11, 2024 7:20 pm

Re: Help with Repeatable Conversation and Node Tracking

Post by caltaylor101 »

Hello, thanks for your help! I think my goal might be a little different than what you described.

What I’m aiming for is to keep Conversation B as a standalone sequence that can be used across different contexts. Conversation B would act as a reusable “action dialogue” that could be triggered at various points within other conversations.

Ideally, I’d like a way to start Conversation B from within any other conversation, have a sequence of actions play out in Conversation B, and then automatically return to the exact point in the original conversation where it was triggered once Conversation B finishes. This way, I can incorporate Conversation B into multiple conversations without needing to duplicate it or modify each time.

Conversation A.png
So in this mock example, I want to save the circled node.
Then if the player fights, they are taken to Conversation B, where there is a repeatable format I can reuse and inject anywhere else.

When Conversation B ends, it ideally goes to that circled node in Conversation A.
And later on, another node in that conversation.


Does that make sense? Thanks again for your help!

Hmm, would something like this work?
So far it works for my specific case, but i would also like to know how to target specific nodes in a conversation!

Code: Select all


public void SwitchToConversationAction(string conversation)
{
    _lastConversationID = DialogueManager.currentConversationState.subtitle.dialogueEntry.id;
    ConversationPositionStack.PushConversationPosition();
    DialogueManager.StartConversation(conversation);
}

public void ContinueConversation()
{
    var conversationTitle = DialogueManager.GetConversationTitle(_lastConversationStarted);
    DialogueManager.StartConversation(conversationTitle);
    ConversationPositionStack.PopConversationPosition();
}
User avatar
Tony Li
Posts: 22104
Joined: Thu Jul 18, 2013 1:27 pm

Re: Help with Repeatable Conversation and Node Tracking

Post by Tony Li »

Hi,

The conversation position stack was exactly what I was going to suggest. So I think you're on the right track there.

To start a conversation at a specific dialogue entry, you need to know its entry ID. Then pass the entry ID as the 4th parameter, like:

Code: Select all

Transform actor = DialogueManager.currentActor;
Transform conversant = DialogueManager.currentConversant;
DialogueManager.StartConversation(conversation, actor, conversant, entryID);
If you know the entry's Title but not its ID, you can get it like this:

Code: Select all

Conversation otherConversation = DialogueManager.masterDatabase.GetConversation(conversation);
int entryID = otherConversation.dialogueEntries.Find(entry => entry.Title == "Some Title").id;
Transform actor = DialogueManager.currentActor;
Transform conversant = DialogueManager.currentConversant;
DialogueManager.StartConversation(conversation, actor, conversant, entryID);
caltaylor101
Posts: 7
Joined: Mon Nov 11, 2024 7:20 pm

Re: Help with Repeatable Conversation and Node Tracking

Post by caltaylor101 »

Thanks for the help, I'm still a bit confused but I'm moving forward again :)
I think this is resolved.

I think I'm confusing myself with the order of execution:
Actions to run when the node is spoken. You can use the "..." dropdown menu or enter Lua code directly. NOTE: The Script field runs before the property DialogueManager.currentConversationState is set. This is because it's possible that the Script field might affect the value of DialogueManager.currentConversationState. If custom functions in Script need to access DialogueManager.currentConversationState, write them to wait until the end of the frame.
So it effects the state if I change conversations, but doesn't if I make a choice?

What's weird is my Hello Enemy node gets saved if I wait for end of frame or don't.
It's not unless I change conversations and start it back up will it not work how I expected.


WaitForEndOfFrame() fixed my issue between Conversations, but I don't understand why it works fine between nodes.
With no Wait, My function saves the Hello Enemy node the first time, but fails the second time.
With a Wait, it still saves Hello Enemy node, but also saves it when it starts the conversation up again.

Code: Select all

    private int _lastNodeID;
    private string _lastConversationStarted; 


    public void SwitchToConversationAction(string conversation)
    {
        StartCoroutine(SwitchToConversationActionWork(conversation));
    }

    public IEnumerator SwitchToConversationActionWork(string conversation)
    {
    	//Call End of Frame here so node values are what's expected. 
        yield return new WaitForEndOfFrame();
        _lastConversationStarted = DialogueManager.lastConversationStarted;
        _lastNodeID = DialogueManager.currentConversationState.subtitle.dialogueEntry.id;
        DialogueManager.StopConversation();
        DialogueManager.StartConversation(conversation);
    }

    public void ContinueConversation()
    {
        DialogueManager.StopConversation();
        DialogueManager.StartConversation(_lastConversationStarted, null, null, _lastNodeID);
    }

Attachments
Conversation A.png
Conversation A.png (17.82 KiB) Viewed 238 times
User avatar
Tony Li
Posts: 22104
Joined: Thu Jul 18, 2013 1:27 pm

Re: Help with Repeatable Conversation and Node Tracking

Post by Tony Li »

Hi,

When you push a dialogue entry node such as "Hello enemy" and then pop it, the conversation will return to that node and play it again. What would you like to happen instead?
caltaylor101
Posts: 7
Joined: Mon Nov 11, 2024 7:20 pm

Re: Help with Repeatable Conversation and Node Tracking

Post by caltaylor101 »

Sorry been out and haven't been able to return to this project for a few weeks.

I'm confused with how it works. So my expected result is that if I run this:

Code: Select all

_lastConversationStarted = DialogueManager.lastConversationStarted;
_lastNodeID = DialogueManager.currentConversationState.subtitle.dialogueEntry.id;
DialogueManager.StopConversation();
DialogueManager.StartConversation(conversation);
I expect that if I have a conversation A:

Node1 => Node2 => Node3 => Node4 => Node5

I run the above code on Node5, so I expect it to give me Node4. Good.

But if I switch to Conversation B and run through it:

Conversation A Node 5 => ConversationB (Node 1-3) => Conversation A Node 4 => Conversation A Node 5

If I run the above code again on Node5, then it will grab the values of Conversation B Node 3.

What I see is a skipped node, and the only thing I can think of is that maybe because Conversation A is being started, there is some sort of behavior or delay I'm unaware of.

The way I'm fixing this perceived unexpected behavior is by using a WaitTillEndOfFrame().

The issue is probably my lack of understanding of the workflow.
User avatar
Tony Li
Posts: 22104
Joined: Thu Jul 18, 2013 1:27 pm

Re: Help with Repeatable Conversation and Node Tracking

Post by Tony Li »

Hi,

If you're using the conversation position stack, you shouldn't need to stop and start conversations. Would you please remind me what your current setup is?
Post Reply