Multiple Small Questions regarding the Dialogue System

Announcements, support questions, and discussion for the Dialogue System.
The_Kihng
Posts: 11
Joined: Fri Aug 25, 2023 10:23 am

Multiple Small Questions regarding the Dialogue System

Post by The_Kihng »

Hi, this is my first time posting here. I just want to begin by saying that this is an amazing asset you've created, and it's been quite fun for the most part to learn. I had a few questions on how to finish up customizing my UIs and conversations.

-Variables: I've set up an example conversation where talking to the NPC increases a variable each time, allowing for different texts. I thought this would be useful for interactable objects, as they could each have an instance of this variable that raises when examined. I had this setup in a previous engine I've now abandoned, and it worked amazingly, but I've yet to determine how to do this in Unity. While I do know a bit of C#, I'm unfamiliar with both Lua and the methods and classes of this asset. This seems easy in my head, but I need a nudge in the correct direction.

-Hiding Portraits and Names: On that note, I need to be able to easily hide the portrait section of the UI. I've pretty heavily customized the JRPG template and have everything related to portraits under the Portrait Panel, but I don't know how to disable and reenable this as needed through Lua or C#. I should note that I have almost no experience working with UI using direct code, and learning from this asset has actually been my first real experience working with UI entirely! I found many results related to this topic in my searches, but nothing exactly matching my needs.

-Cancelled Conversations: I've found some settings related to cancelling the conversation when the player walks away. This works great on its own, but I'd also like to change a variable noting that the player walked away from the conversation, and have the NPC react to it, maybe with a bark at that moment or a different conversation when you next talk to them. I'm unsure how to trigger the variable change when this happens, unfortunately.

-Keyboard Navigation: I'm sorry, I'm sure you get asked this a lot, but I just wasn't able to figure it out, even after looking it up. I want to navigate dialogue choices using the keyboard. I tried to enable this by adding the GUI Control script to the Response Menu Panel and enabling the Navigation option, but this didn't work. I think I'm close, however. The other issue is that the same keys used for movement would also be used for navigation, so I'd need the player to be able to move around (and potentially cancel the conversation if they wander off) until a choice comes up, which would prevent the player from moving while the choice remains on-screen.

Items: The items variable sticks out to me because of how little functionality it has. Just a name, description, and seemingly the ability to instance it?? I don't know. Am I missing something here? What is this for?

I'm really sorry if a lot of these questions are just me being dumb, but thank you in advance for any help you can give me. :)

Edit: Just remembered. I'd also like to ask about text appearing one character at a time. I saw a setting for "Typewriter text"? Or something like that anyway. I wanted dialogue text to appear .. not all at once, if you understand. Is this possible, and if so, how? Also being able to adjust the speed of the text would be nice.
User avatar
Tony Li
Posts: 21679
Joined: Thu Jul 18, 2013 1:27 pm

Re: Multiple Small Questions regarding the Dialogue System

Post by Tony Li »

Hi,

Thanks for using the Dialogue System!
The_Kihng wrote: Fri Aug 25, 2023 4:17 pm-Variables: I've set up an example conversation where talking to the NPC increases a variable each time, allowing for different texts. I thought this would be useful for interactable objects, as they could each have an instance of this variable that raises when examined. I had this setup in a previous engine I've now abandoned, and it worked amazingly, but I've yet to determine how to do this in Unity. While I do know a bit of C#, I'm unfamiliar with both Lua and the methods and classes of this asset. This seems easy in my head, but I need a nudge in the correct direction.
No need for any scripting. Define your variable in the Dialogue Editor's Variable section. In the first dialogue entry node of your conversation (the node linked from <START>), click the "..." next to the Script field. Click "+", then set the dropdowns to Set > Variable > (your-variable-name) > Add > 1. Then click Apply. This will increment your variable every time the conversation starts.

One thing to note: Conversations Evaluate Conditions One Extra Level Ahead

Also related: How To: Run a Conversation Only Once / Different Second Time
The_Kihng wrote: Fri Aug 25, 2023 4:17 pm-Hiding Portraits and Names: On that note, I need to be able to easily hide the portrait section of the UI. I've pretty heavily customized the JRPG template and have everything related to portraits under the Portrait Panel, but I don't know how to disable and reenable this as needed through Lua or C#. I should note that I have almost no experience working with UI using direct code, and learning from this asset has actually been my first real experience working with UI entirely! I found many results related to this topic in my searches, but nothing exactly matching my needs.
Try this:
  • Make sure the GameObject named "Portrait Panel" is uniquely named. If not, give it a unique name.
  • Add a Canvas Group component to the portrait panel. Set its Alpha to zero. Then disable the Canvas Group by unticking the checkbox next to the component name.
  • When you want to hide the portrait panel, use this sequencer command in your dialogue entry node:

    Code: Select all

    {{default}}; SetEnabled(CanvasGroup, true, Portrait Panel)
    The {{default}} runs the Dialogue Manager's Default Sequence. The SetEnabled() command enables the Canvas Group, which will hide the portrait panel.
  • When you want to show the portrait panel, use this sequencer command in your dialogue entry node:

    Code: Select all

    {{default}}; SetEnabled(CanvasGroup, false, Portrait Panel)
The_Kihng wrote: Fri Aug 25, 2023 4:17 pm-Cancelled Conversations: I've found some settings related to cancelling the conversation when the player walks away. This works great on its own, but I'd also like to change a variable noting that the player walked away from the conversation, and have the NPC react to it, maybe with a bark at that moment or a different conversation when you next talk to them. I'm unsure how to trigger the variable change when this happens, unfortunately.
There are two ways to do this:

1. Without scripting, although somewhat awkward: Set the "walked away" variable to true at the start of the conversation. In the last dialogue entry node of the conversation, set the variable false.

2. With scripting: Make a subclass of DialogueSystemTrigger and use this in place of DialogueSystemTrigger. Override the StopActiveConversation() method. Example:

Code: Select all

public class MyCustomDialogueSystemTrigger : DialogueSystemTrigger
{
    protected override void StopActiveConversation()
    {
        DialogueLua.SetVariable("walkedAway", true);
        base.StopActiveConversation();
    }
}
The_Kihng wrote: Fri Aug 25, 2023 4:17 pm-Keyboard Navigation: I'm sorry, I'm sure you get asked this a lot, but I just wasn't able to figure it out, even after looking it up. I want to navigate dialogue choices using the keyboard. I tried to enable this by adding the GUI Control script to the Response Menu Panel and enabling the Navigation option, but this didn't work. I think I'm close, however. The other issue is that the same keys used for movement would also be used for navigation, so I'd need the player to be able to move around (and potentially cancel the conversation if they wander off) until a choice comes up, which would prevent the player from moving while the choice remains on-screen.
On the Dialogue Manager GameObject, tick the Input Device Manager component's Always Auto Focus. This will keep a response menu button focused (selected) when showing a response menu so you can navigate among them. The Dialogue System uses plain old Unity UI navigation to navigate menus. As long as your EventSystem works, you'll be able to navigate all Dialogue System UIs with the keyboard or joystick. If you want the player to be able to move during conversations, you'll need to map different Vertical and Horizontal inputs to your EventSystem than those used for player movement. If you want to disable player movement during conversations, see 07:00 of the Interaction Tutorial.
The_Kihng wrote: Fri Aug 25, 2023 4:17 pmItems: The items variable sticks out to me because of how little functionality it has. Just a name, description, and seemingly the ability to instance it?? I don't know. Am I missing something here? What is this for?
Except for quests, it's not used for anything in particular. You can use it for whatever you like, or just ignore it. The one important thing it's used for is to hold information about quests. (Quests and items share the same data table because the Dialogue System uses the same data structure as a pro writing app called Chat Mapper.)
The_Kihng wrote: Fri Aug 25, 2023 4:17 pmEdit: Just remembered. I'd also like to ask about text appearing one character at a time. I saw a setting for "Typewriter text"? Or something like that anyway. I wanted dialogue text to appear .. not all at once, if you understand. Is this possible, and if so, how? Also being able to adjust the speed of the text would be nice.
Add a typewriter effect to your subtitle text GameObject. If you're using UI Text, add a UnityUITypewriterEffect component. If you're using TextMesh Pro (see TextMesh Pro Support), use TextMeshProTypewriterEffect. If you're using Text Animator for Unity (see integration), it gives you options for very fancy typing.

To adjust the speed, set the typewriter effect's Characters Per Second. You can also add RPG Maker-style control codes into your text to make it pause, appear immediately, etc.

If you're using continue buttons to advance the conversation, you may want the first click of a continue button to fast-forward the typewriter if it's still typing. The UI prefabs that ship with the Dialogue System behave like this. They use StandardUIContinueButtonFastForward components.

If you want to change the typewriter speed at runtime, see: How To: Adjust Typewriter Speed.
The_Kihng
Posts: 11
Joined: Fri Aug 25, 2023 10:23 am

Re: Multiple Small Questions regarding the Dialogue System

Post by The_Kihng »

Thank you very much! Most of this looks correct except for the variable one. This is my fault as I failed to actually mention the problem, haha. I already know how to raise the variable. That was fairly easy. The issue is that the variable is shared between all conversations at once, meaning if you talk to NPC A 3 times and then talk to NPC B, NPC B will act as if you've already spoken to them because they're using the same variable. Hence why I mentioned having an instance of the variable for each object- that was the part I couldn't figure out.

I'll work on implementing the rest of your advice. Thank you again for the quick reply!

Edit: I've almost finished implementing all of your suggestions. Strangely, though I can now navigate the responses with the arrow keys, neither one (I'm using two for this test) highlights at all. No clue why. I've also found that you can group variables (like the walking away one) by naming them Bar.var, Foo.var, and so on with var being your variable name. Interesting, but it doesn't solve my variable problem. There would be hundreds of interactable objects, and needing an individual variable in the list for each one would be way too difficult to keep track of, not to mention tedious.
User avatar
Tony Li
Posts: 21679
Joined: Thu Jul 18, 2013 1:27 pm

Re: Multiple Small Questions regarding the Dialogue System

Post by Tony Li »

Hi,

To investigate the navigation highlight issue, keep an inspector view on the EventSystem. At runtime, the bottom of the inspector will report which button is selected (i.e., has navigation focus). If it's reporting the correct button, check the Button component's Transition type. If it's set to Color, make sure the Selected and Highlighted colors are visually different from the Normal color. Also, you may also want to add a Deselect Previous On Pointer Enter component. When you mouse over a button, this component visually deselects the previously-selected button. (Surprisingly, Unity UI doesn't do this by default.)

For the variables, there are a few approaches you could take. The "no C# scripting" way would be to change the node's Script field. You don't have to define variables ahead of time in the Dialogue Editor's Variables section. For a character named Foo, you could set the first node's Script to:

Code: Select all

if (Variable["Foo"] == nil) then Variable["Foo"] = 1 else Variable["Foo"] = Variable["Foo"] + 1 end
That's admittedly verbose. But, wait, it can get even more verbose. ;-) You can use this same Script for all interactable objects:

Code: Select all

if (Variable[Variable["ConversantIndex"]] == nil) then Variable[Variable["ConversantIndex"]] = 1 else Variable[Variable["ConversantIndex"]] = Variable[Variable["ConversantIndex"]] + 1 end
When a conversation starts, the Dialogue System sets Variable["ConversantIndex"] to the name of the conversant as it appears in the Actor[] Lua table. So if the actor were "Foo", then Variable["ConversantIndex"] would be "Foo", which would make the line immediately above functionally the same as the one above it.


If you don't mind doing a little C# scripting, you could add a script to the Dialogue Manager that has an OnConversationStart(Transform) method. (Reference: Special Script Methods.) It could look like:

Code: Select all

void OnConversationStart(Transform actor)
{
    string conversantVariableName = DialogueLua.GetVariable("ConversantIndex").asString;
    DialogueLua.SetVariable(conversantVariableName, 1 + DialogueLua.GetVariable(conversantVariableName).asInt);
}[/code]

This will automatically create/increment a variable that has the same name as the value of Variable["ConversantIndex"]. No need for any Script fields in your conversations.
The_Kihng
Posts: 11
Joined: Fri Aug 25, 2023 10:23 am

Re: Multiple Small Questions regarding the Dialogue System

Post by The_Kihng »

So it turns out that the highlight is indeed working, but it is *extremely* hard to see. Even with the colors set to complete opposite ends of the spectrum, it can be hard to tell which is highlighted. Now that I know it's working though, I can tinker with it.

I'd like to add a little animated pointer to the highlighted option. I think that'd help a lot, and I already have one on hand. I already added a different one to the continue button, but this would be a bit more complicated as it has to move to the highlighted option, no?

I like all of the options for the variables. Verbose is often better! If I choose the C# option, will I have to add it to the assembly thing? Assemblies hurt and confuse me and I'd rather avoid that, unless it's super simple. I spent a couple hours yesterday screaming at the asset that imports the .asmdef files thinking it WAS the .asmdef file and I couldn't figure out why I couldn't make an assembly reference with it.... To be fair, the name was very misleading. (I was trying to reference a namespace in one of the assembly scripts and it didn't like that. Eventually I just made the reference to the assembly in the namespace instead and it worked. Go figure.)
User avatar
Tony Li
Posts: 21679
Joined: Thu Jul 18, 2013 1:27 pm

Re: Multiple Small Questions regarding the Dialogue System

Post by Tony Li »

Hi,

Regarding asmdefs, the Dialogue System doesn't use them by default, but you can import the DialogueSystemAssemblyDefinitions.unitypackage file located inside the Dialogue System's Scripts folder if you want them. The Dialogue System is, however, inside a special folder named Plugins. (See: Special folders.) Unity compiles scripts inside the Plugins folder before any scripts that are outside of Plugins, and scripts inside Plugins have no access to scripts outside of Plugins. This two-stage compilation process lets Unity skip recompiling Plugins unless a script inside Plugins has changed. This speeds up compilation since you can modify your own scripts that are outside of Plugins, and Unity only needs to recompile your scripts without having to also recompile Plugins. Your scripts that are outside of Plugins can access scripts in Plugins.

For the animated pointer, I recommend adding an animated pointer to all response buttons. If you're using the StandardUIMenuPanel's Button Template, which instantiates buttons at runtime as needed for each menu, you'd just add the animated pointer to the response button template. Change the Button component's Transition dropdown to Animation. This will set up the button to play animation clips when it changes state from normal to highlighted, selected, etc. Use Unity's Animation window to edit the animations. Animations in Unity can animate any property. In this case, configure the Normal animation to deactivate the animated pointer GameObject. Configure the Selected and Highlighted animations to activate and animate the pointer.
The_Kihng
Posts: 11
Joined: Fri Aug 25, 2023 10:23 am

Re: Multiple Small Questions regarding the Dialogue System

Post by The_Kihng »

That's odd. I wasn't able to get the Dialogue System to recognize the New Input System's InputActionAsset (I think it's called that?) until I made an assembly reference asset and made a direct register in the code of

Code: Select all

PixelCrushers.InputDeviceManager.RegisterInputAction("InteractGeneric", playerInputActions.Player.InteractGeneric);
If what you're saying is correct (and you have been every time so far! You really know your stuff. :D) then the Assembly Reference was unnecessary? The whole plugins folder thing explains why I couldn't reference my namespace from your scripts though, so thank you for telling me that.

Regardless, I should just be able to add the variable script to the Dialogue Manager object, no fancy steps needed?

As for the animated pointer, I will try that. Thank you for the detailed advice. Hopefully I won't need anymore help after this. Don't want to take up too much of your time, haha.
User avatar
Tony Li
Posts: 21679
Joined: Thu Jul 18, 2013 1:27 pm

Re: Multiple Small Questions regarding the Dialogue System

Post by Tony Li »

The_Kihng wrote: Sat Aug 26, 2023 12:03 pmThat's odd. I wasn't able to get the Dialogue System to recognize the New Input System's InputActionAsset (I think it's called that?) until I made an assembly reference asset and made a direct register in the code of

Code: Select all

PixelCrushers.InputDeviceManager.RegisterInputAction("InteractGeneric", playerInputActions.Player.InteractGeneric);
If what you're saying is correct (and you have been every time so far! You really know your stuff. :D) then the Assembly Reference was unnecessary? The whole plugins folder thing explains why I couldn't reference my namespace from your scripts though, so thank you for telling me that.
You're correct. You need to use InputDeviceManager.RegisterInputAction() for the Dialogue System to be able to recognize an input action.
The_Kihng wrote: Sat Aug 26, 2023 12:03 pmRegardless, I should just be able to add the variable script to the Dialogue Manager object, no fancy steps needed?
That's correct, too.
The_Kihng wrote: Sat Aug 26, 2023 12:03 pmAs for the animated pointer, I will try that. Thank you for the detailed advice. Hopefully I won't need anymore help after this. Don't want to take up too much of your time, haha.
I'm here to help, so if you have any questions please feel free to ask.
The_Kihng
Posts: 11
Joined: Fri Aug 25, 2023 10:23 am

Re: Multiple Small Questions regarding the Dialogue System

Post by The_Kihng »

I was hoping to avoid this, but it seems I'm quite stuck. I just spent a good 4 hours getting the animated cursor to work properly. It now successfully works! (My problem was that I tried doing it through the Animator rather than the Animation window.) However, the cursor is slow to disappear after switching to another option, allowing, if briefly, for multiple cursors at once. I tried adjusting the speed settings of the Animator Controller, but it didn't seem to have an effect.

I also implemented the variable script you wrote... and now I can't talk to anyone. It seems there's something wrong with the conditional. Here it is:

Code: Select all

Variable["ConversantIndex"] == 0
I also tried null instead of 0 just in case but that didn't help sadly. I then tried adding a line to the script to print the value of ConversantIndex, but it did nothing. Which is odd.

Code: Select all

Debug.Log(DialogueLua.GetVariable(conversantVariableName).asInt);
I know the Conversation is being triggered because the console says it is. It's just rejecting every conditional.

Not sure what's going on here, honestly.
User avatar
Tony Li
Posts: 21679
Joined: Thu Jul 18, 2013 1:27 pm

Re: Multiple Small Questions regarding the Dialogue System

Post by Tony Li »

The_Kihng wrote: Sat Aug 26, 2023 10:56 pm...the cursor is slow to disappear after switching to another option, allowing, if briefly, for multiple cursors at once. I tried adjusting the speed settings of the Animator Controller, but it didn't seem to have an effect.
In your animator controller, inspect the transition arrows. UNtick Has Exit Time. Otherwise it will wait for the animation to finish a complete loop before transitioning.
The_Kihng wrote: Sat Aug 26, 2023 10:56 pmI also implemented the variable script you wrote... and now I can't talk to anyone. It seems there's something wrong with the conditional. Here it is:

Code: Select all

Variable["ConversantIndex"] == 0
Variable["ConversantIndex"] will be the name of the conversant, modified according to these rules so it can be an index in the Lua Actor[] table. An index in a Lua table is like a key in a C# Dictionary.

If the conversant's Name is "Bob", the ConversantIndex will be "Bob".

If the conversant's Name is "Bob the Builder", the ConversantIndex will be "Bob_the_Builder".

Note: In contrast, Variable["Conversant"] will be conversant's display name. If you've set the conversant's Name to "Bob", ticked Use Display Name, and set Display Name to "Bob the Builder", then Variable["Conversant"] will be "Bob the Builder" and Variable["ConversantIndex"] will be "Bob". If you haven't ticked Use Display Name, both values will be "Bob".
Post Reply