Retain conversation on screen through multiple interactions

Announcements, support questions, and discussion for the Dialogue System.
Post Reply
zenmaster
Posts: 7
Joined: Mon May 24, 2021 10:10 am

Retain conversation on screen through multiple interactions

Post by zenmaster »

Hiya!

Running through parts of the tutorials here and wondering if this is on the right track or not?

I have one conversation (image attached), and one quest. I've got a bunch of conversation child nodes that are set with conditions based on the status of the quest (condition code written in red next to each node).
findbabies.png
findbabies.png (137.54 KiB) Viewed 470 times
I start the conversation in code by using StartConversation and a public field string field using [ConversationPopup] to set the conversation in the inspector. I don't have NPCs in the game to initiate conversations, it's coming through a mobile phone UI interface like texts or DMs.

The "Ok sure!" node as you can see (selected in the inspector) sets the quest state to active, and then as the game determines the quest has been successful I can mark it as a success with QuestLog.SetQuestState("FindBabies", QuestState.Success) (could you confirm that this is the correct way?)

As I return to the conversation during each different quest state, I would like it to remember the previous conversation entries on screen instead of it starting from a clear slate again. Is this possible?

I've looked through the textline example as this seemed to be headed in the right direction but couldn't quite find what I was after. Perhaps it's something to do with utilising the conversation stack but I want to be sure I'm not overthinking it!

Just to be clear the UI output would be something like (using the above example):

> Find me some babies
>> Ok sure!
[player closes UI interface, does a bunch of stuff, opens UI interface and kicks off StartConversation again]
> Still working on it??
>> Yes!
[player closes UI interface, does more stuff, successfully finishing the quest, opens UI interface and kicks off StartConversation again]
> Thank you for finding them!


Bonus question! Could those conversation entries be displayed on screen in reverse order (latest at the top, earliest at the bottom)?

Thank you for your help.


(perhaps it's something more like a "resume conversation" I'm after... just thinking out loud now)
User avatar
Tony Li
Posts: 22049
Joined: Thu Jul 18, 2013 1:27 pm

Re: Retain conversation on screen through multiple interactions

Post by Tony Li »

Hi!
zenmaster wrote: Mon May 24, 2021 12:30 pmThe "Ok sure!" node as you can see (selected in the inspector) sets the quest state to active, and then as the game determines the quest has been successful I can mark it as a success with QuestLog.SetQuestState("FindBabies", QuestState.Success) (could you confirm that this is the correct way?)
That's correct.
zenmaster wrote: Mon May 24, 2021 12:30 pmAs I return to the conversation during each different quest state, I would like it to remember the previous conversation entries on screen instead of it starting from a clear slate again. Is this possible?
Yes. I'll describe how to do it using the SMS Dialogue UI prefab in Plugins / Pixel Crushers / Dialogue System / Prefabs / Standard UI Prefabs / Pro, or the Textline package. However, you can provide your own code instead. Look at the script ConversationLogger.cs for an example.

If you use SMSDialogueUI/Textline then, before leaving the conversation, call the SMSDialogueUI component's OnRecordPersistentData() method. (Also tick the SMSDialogueUI's Use Conversation Variable checkbox if your game will have more than one conversation.)

To resume the conversation, call the SMSDialogueUI's OnApplyPersistentData(). If your game has more than one conversation, set the Conversation variable first. C# code:

Code: Select all

DialogueLua.SetVariable("Conversation", YourConversationTitle);
You don't need to use the conversation position stack. The conversation position stack is used to record a conversation position so you can dive into a side conversation and then pop back to the recorded position.
zenmaster wrote: Mon May 24, 2021 12:30 pmBonus question! Could those conversation entries be displayed on screen in reverse order (latest at the top, earliest at the bottom)?
Yes, by making a subclass of SMSDialogueUI. Override the AddMessage() method to put the newly-added entry to the top. Roughly:

Code: Select all

public class MyDialogueUI : SMSDialogueUI
{
    protected override void AddMessage(Subtitle subtitle)
    {
        base.AddMessage(subtitle);
        var lastEntry = messagePanel.transform.GetChild(messagePanel.transform.childCount - 1);
        lastEntry.SetAsFirstFirstSibling();
    }
}
You'll probably also want to override the ScrollToBottom() method to either do nothing or scroll to the top. I think scrolling to the top may be redundant, since it should stay at the top anyway.
zenmaster
Posts: 7
Joined: Mon May 24, 2021 10:10 am

Re: Retain conversation on screen through multiple interactions

Post by zenmaster »

Legend, thanks for the quick response Tony.

I'll jump on this right now. Will look at the SMS stuff to start, thanks for the heads up!
User avatar
Tony Li
Posts: 22049
Joined: Thu Jul 18, 2013 1:27 pm

Re: Retain conversation on screen through multiple interactions

Post by Tony Li »

Glad to help!

If you prefer to code up the behavior yourself, you don't have to use SMSDialogueUI. You can make your own subclass of StandardDialogueUI to inherit the Standard Dialogue UI stuff, or even make your own implementation of the base IDialogue C# interface if you want to start from a bare-bones UI.
zenmaster
Posts: 7
Joined: Mon May 24, 2021 10:10 am

Re: Retain conversation on screen through multiple interactions

Post by zenmaster »

zenmaster wrote: Mon May 24, 2021 12:30 pmAs I return to the conversation during each different quest state, I would like it to remember the previous conversation entries on screen instead of it starting from a clear slate again. Is this possible?
Yes. I'll describe how to do it using the SMS Dialogue UI prefab in Plugins / Pixel Crushers / Dialogue System / Prefabs / Standard UI Prefabs / Pro, or the Textline package. However, you can provide your own code instead. Look at the script ConversationLogger.cs for an example.

If you use SMSDialogueUI/Textline then, before leaving the conversation, call the SMSDialogueUI component's OnRecordPersistentData() method. (Also tick the SMSDialogueUI's Use Conversation Variable checkbox if your game will have more than one conversation.)

To resume the conversation, call the SMSDialogueUI's OnApplyPersistentData(). If your game has more than one conversation, set the Conversation variable first. C# code:

Code: Select all

DialogueLua.SetVariable("Conversation", YourConversationTitle);
The OnRecordPersistenData and OnApplyPersistentData methods work quite well!

Though calling StartConversation after OnApplyPersistentData clears the messages (because in Open it calls DestroyInstantiatedMessages). [And to be transparent I'm using the textline prefab for now, though I did try it with sms and I can also see they both destroy the messages in Open.]

Was I not meant to call StartConversation after OnApplyPersistentData? If I don't I'm not sure how I'm supposed to get the conversation to loop back to the start (to read the child nodes and then pick the correct one based on the quest state condition, then display the corresponding messages).


Alternatively removing DestroyInstantiatedMessages from Open actually works out alright for the short term, as long as I limit the amount of times I call StartConversation to when the quest state changes (and I assume there is a way of getting notified when a quest state changes... well OnQuestStateChange looks like it'll do the trick).
User avatar
Tony Li
Posts: 22049
Joined: Thu Jul 18, 2013 1:27 pm

Re: Retain conversation on screen through multiple interactions

Post by Tony Li »

zenmaster wrote: Mon May 24, 2021 10:55 pmWas I not meant to call StartConversation after OnApplyPersistentData? If I don't I'm not sure how I'm supposed to get the conversation to loop back to the start (to read the child nodes and then pick the correct one based on the quest state condition, then display the corresponding messages).
I didn't realize you want to loop back to the start. The Textline/SMSDialogueUI scripts don't do that. They assume you're resuming from the point you left the conversation. You'll need to modify the script or write a separate script that logs the conversation's history and repopulates the UI when the conversation starts.
zenmaster
Posts: 7
Joined: Mon May 24, 2021 10:10 am

Re: Retain conversation on screen through multiple interactions

Post by zenmaster »

Tony Li wrote: Tue May 25, 2021 7:49 am
zenmaster wrote: Mon May 24, 2021 10:55 pmWas I not meant to call StartConversation after OnApplyPersistentData? If I don't I'm not sure how I'm supposed to get the conversation to loop back to the start (to read the child nodes and then pick the correct one based on the quest state condition, then display the corresponding messages).
I didn't realize you want to loop back to the start. The Textline/SMSDialogueUI scripts don't do that. They assume you're resuming from the point you left the conversation. You'll need to modify the script or write a separate script that logs the conversation's history and repopulates the UI when the conversation starts.
Yep that's totally cool! I sort of figured it was headed this way.

And yes sorry perhaps my wording was a bit unclear! I guess at the end of the day I wanted to have multiple branches of dialogue from the same conversation appear sequentially without being cleared.

As for the best place to attack it, do you think looking at ShowSubtitle is the way? As you say I can keep a history and then show that before restoring the current spot in the conversation. Between looking through how AddMessage and AddRecord work I think it's completely fine from here.

Thanks!
User avatar
Tony Li
Posts: 22049
Joined: Thu Jul 18, 2013 1:27 pm

Re: Retain conversation on screen through multiple interactions

Post by Tony Li »

Hi,

ShowSubtitle is a perfectly good way to do it.

There's also a general-purpose OnConversationLine method, but since you're probably already subclassing StandardDialogueUI you might as well use what it has.
zenmaster
Posts: 7
Joined: Mon May 24, 2021 10:10 am

Re: Retain conversation on screen through multiple interactions

Post by zenmaster »

Tony Li wrote: Tue May 25, 2021 8:38 am Hi,

ShowSubtitle is a perfectly good way to do it.

There's also a general-purpose OnConversationLine method, but since you're probably already subclassing StandardDialogueUI you might as well use what it has.
Exactly :D

I'll have a look at OnConversationLine too.

Thanks again for everything!
Post Reply