Hello,
I am creating a game that highly utilizes the Dialogue System for Unity, as the game is very text-based. I was wondering if there was any way to create 2 things:
1) An auto button, which triggers a flag of sorts, telling the dialogue system to continue the text automatically based on the voice acting audio length of each dialogue node. For nodes where there are no voice acting, I want it to continue to the next node automatically based on the text length of the current node.
2) A skip button, which triggers the dialogue system to automatically (and immediately) click through the nodes if they have been previously read at any point of the game (regardless of save file). The skip button will untrigger as soon as it reaches a node that has not been previously read.
Any tips on how to go about starting these? The skip button is what I believe would be the more difficult task. Any information would be great, thanks!
Auto/ Skip buttons?
Re: Auto/ Skip buttons?
I'm not the expert around here, but I can suggest you look at the following sequencer commands:
SetContinueMode - enable/disable the continue button
AudioWait - plays an audio clip, and waits until it's done before doing the next thing
Delay - waits before doing the next thing, even if you don't have an audio clip playing
SetContinueMode - enable/disable the continue button
AudioWait - plays an audio clip, and waits until it's done before doing the next thing
Delay - waits before doing the next thing, even if you don't have an audio clip playing
Arcanoria Games - http://www.arcanoria.com - indie game development blog
twitter: https://twitter.com/WaltCollins3 @WaltCollins3
Game titles: Pesticide Patrol, Arcanoria Chronicles, CyberGhost, Arcanoria
PLAY NOW: http://arcanor.itch.io/
twitter: https://twitter.com/WaltCollins3 @WaltCollins3
Game titles: Pesticide Patrol, Arcanoria Chronicles, CyberGhost, Arcanoria
PLAY NOW: http://arcanor.itch.io/
Re: Auto/ Skip buttons?
Hi,
The easiest workflow is to set the Dialogue Manager's Default Sequence to:
If your dialogue entry nodes don't define their own sequences in their Sequence fields, they'll use this Default Sequence.
Both commands, AudioWait and Delay, run in parallel as soon as the dialogue entry is shown, since neither has an "@time" bit at the end. (If you wanted to play an explosion sound at the 1-second mark, for example, you could use the command Audio(Explosion)@1.)
The Delay command waits for a duration specified by the special keyword '{{end}}'. The Dialogue System computes the value of the '{{end}}' keyword based on the text length and the Dialogue Manager's Subtitle Settings.
The AudioWait command waits until the audio clip is done. If you're using lipsync, this might be a different command such as SALSA, depending on how you're doing lipsync.
The keyword 'entrytag' is special. Every dialogue entry has a unique entrytag. If you name each voice acting file according to its entrytag, the Default Sequence above will automatically find it. This way you don't have to manually enter a different filename in each dialogue entry's Sequence field.
Voice acting almost always runs longer than the value of '{{end}}', so I think it's fine to include both commands (AudioWait and Delay) in the same sequence. If AudioWait doesn't find a corresponding audio clip (i.e., no voice acting available), it will log a warning to the console and do nothing. The duration will then fall to the Delay command.
If you don't want to use entrytag, you can always set each one manually in the dialogue entry node's Sequence field.
One approach is to use SimStatus and set nodes' False Condition Action to Passthrough.
SimStatus records an extra piece of information for every dialogue entry node. It increases the memory footprint of the Lua environment and the size of saved games, so it's something to keep in mind for really huge dialogue databases. The Dialogue System's data structure is based on Chat Mapper. SimStatus comes from Chat Mapper and is best documented in the Chat Mapper manual. Expand Scripting with Lua and click on Conditions and Scripts.
The SimStatus for every dialogue entry node starts as 'Untouched'. If the node has been read, its SimStatus is marked 'WasDisplayed'. If the node was offered in a response menu but not selected yet, its SimStatus is marked 'WasOffered'.
You can set the nodes' Conditions fields to check the SimStatus value, such as:
This means, "this node is only true if it hasn't been read yet." Since this is an advanced feature, the Lua wizard doesn't include a drop-down for it. You'll have to type it manually. The '4' is the dialogue entry node's ID, which is shown in the inspector.
Then set the False Condition Action to Passthrough. By default, it's set to Block, which stops evaluation. When it's Passthrough, the conversation will skip through the links until it finds a node whose Conditions are true (i.e., not read yet).
There are two things to consider with this:
1. SimStatus is included in saved game files. If you use the Dialogue System's save system, when you load an older game it will reset SimStatus to the values in that older game.
2. It may be a bit of work to set this up, since you need to specify the dialogue entry node's ID in each Conditions field.
An as alternative, you could add a short script to the Dialogue Manager that has an OnConversationLine method. The Dialogue System calls this method before showing each line. In your method, you could:
1. Check if the dialogue entry has already been read. If so, set the sequence to 'None()', which skips the line.
2. Otherwise mark the entry as read.
Here's a rough sketch of the code. You'll have to provide your own implementation of HasRead() and MarkAsRead(). You can record this info to some kind of permanent storage that's independent of saved games.
I'll offer a couple ideas (mostly based on the good advice Arcanor already offered) that you can play around with to best fit your needs.BaddyDan wrote:1) An auto button, which triggers a flag of sorts, telling the dialogue system to continue the text automatically based on the voice acting audio length of each dialogue node. For nodes where there are no voice acting, I want it to continue to the next node automatically based on the text length of the current node.
The easiest workflow is to set the Dialogue Manager's Default Sequence to:
Code: Select all
AudioWait(entrytag); Delay({{end}})
Both commands, AudioWait and Delay, run in parallel as soon as the dialogue entry is shown, since neither has an "@time" bit at the end. (If you wanted to play an explosion sound at the 1-second mark, for example, you could use the command Audio(Explosion)@1.)
The Delay command waits for a duration specified by the special keyword '{{end}}'. The Dialogue System computes the value of the '{{end}}' keyword based on the text length and the Dialogue Manager's Subtitle Settings.
The AudioWait command waits until the audio clip is done. If you're using lipsync, this might be a different command such as SALSA, depending on how you're doing lipsync.
The keyword 'entrytag' is special. Every dialogue entry has a unique entrytag. If you name each voice acting file according to its entrytag, the Default Sequence above will automatically find it. This way you don't have to manually enter a different filename in each dialogue entry's Sequence field.
Voice acting almost always runs longer than the value of '{{end}}', so I think it's fine to include both commands (AudioWait and Delay) in the same sequence. If AudioWait doesn't find a corresponding audio clip (i.e., no voice acting available), it will log a warning to the console and do nothing. The duration will then fall to the Delay command.
If you don't want to use entrytag, you can always set each one manually in the dialogue entry node's Sequence field.
"Regardless of save file" may be the hard part. I'll get to that in a bit.BaddyDan wrote:2) A skip button, which triggers the dialogue system to automatically (and immediately) click through the nodes if they have been previously read at any point of the game (regardless of save file). The skip button will untrigger as soon as it reaches a node that has not been previously read.
One approach is to use SimStatus and set nodes' False Condition Action to Passthrough.
SimStatus records an extra piece of information for every dialogue entry node. It increases the memory footprint of the Lua environment and the size of saved games, so it's something to keep in mind for really huge dialogue databases. The Dialogue System's data structure is based on Chat Mapper. SimStatus comes from Chat Mapper and is best documented in the Chat Mapper manual. Expand Scripting with Lua and click on Conditions and Scripts.
The SimStatus for every dialogue entry node starts as 'Untouched'. If the node has been read, its SimStatus is marked 'WasDisplayed'. If the node was offered in a response menu but not selected yet, its SimStatus is marked 'WasOffered'.
You can set the nodes' Conditions fields to check the SimStatus value, such as:
Code: Select all
Dialog[4].SimStatus ~= 'WasDisplayed'
Then set the False Condition Action to Passthrough. By default, it's set to Block, which stops evaluation. When it's Passthrough, the conversation will skip through the links until it finds a node whose Conditions are true (i.e., not read yet).
There are two things to consider with this:
1. SimStatus is included in saved game files. If you use the Dialogue System's save system, when you load an older game it will reset SimStatus to the values in that older game.
2. It may be a bit of work to set this up, since you need to specify the dialogue entry node's ID in each Conditions field.
An as alternative, you could add a short script to the Dialogue Manager that has an OnConversationLine method. The Dialogue System calls this method before showing each line. In your method, you could:
1. Check if the dialogue entry has already been read. If so, set the sequence to 'None()', which skips the line.
2. Otherwise mark the entry as read.
Here's a rough sketch of the code. You'll have to provide your own implementation of HasRead() and MarkAsRead(). You can record this info to some kind of permanent storage that's independent of saved games.
Code: Select all
using UnityEngine;
using PixelCrushers.DialogueSystem;
public class MyScript : MonoBehaviour {
public void OnConversationLine(Subtitle subtitle) {
if (HasRead(subtitle.dialogueEntry)) {
subtitle.sequence = "None()"; // Already read, so skip.
} else {
MarkAsRead(subtitle.dialogueEntry);
}
}
}
Re: Auto/ Skip buttons?
Hi Tony,
First, thank you very much for your prompt reply. I wanted to get back to you sooner, but was caught up with a few things and never had the opportunity to until now.
1) Perhaps I should have made this more clear in my initial post, but for the Auto button I wanted to use a toggle to enable/ disable the automatic dialogue accordingly. Of course, I have considered the method you provided, but it does not appear with work with my current workflow.
Each of my nodes has a sequence already attached to it, with their respective commands (whether it's to make the name box appear/ disappear based on character/ narrator dialogue, playing sfx/ voice acting, or animating my character avatars), and I am finding it difficult to use a Default Sequence with this setup.
I was thinking of using that logic to attach a Sequencer Command to the toggle, where the Sequencer Command would take the existing Sequence of the active node, and alter it such that it will run the dialogue with all of its proper Sequences automatically. Disabling/ shutting off the toggle would result in the dialogue system returning to 'manual mode'.
At this point, I only have the general logic down, but have no real foundation as to how else to approach this using the Dialogue System for Unity.
2) I have yet to really explore this option, as I have been stuck on the Auto button/ toggle.
If you could provide any insight as to whether my idea can work, please let me know. Or if you could find a better/ more efficient method, any tips on that would be great as well.
Many thanks in advance!
First, thank you very much for your prompt reply. I wanted to get back to you sooner, but was caught up with a few things and never had the opportunity to until now.
1) Perhaps I should have made this more clear in my initial post, but for the Auto button I wanted to use a toggle to enable/ disable the automatic dialogue accordingly. Of course, I have considered the method you provided, but it does not appear with work with my current workflow.
Each of my nodes has a sequence already attached to it, with their respective commands (whether it's to make the name box appear/ disappear based on character/ narrator dialogue, playing sfx/ voice acting, or animating my character avatars), and I am finding it difficult to use a Default Sequence with this setup.
I was thinking of using that logic to attach a Sequencer Command to the toggle, where the Sequencer Command would take the existing Sequence of the active node, and alter it such that it will run the dialogue with all of its proper Sequences automatically. Disabling/ shutting off the toggle would result in the dialogue system returning to 'manual mode'.
At this point, I only have the general logic down, but have no real foundation as to how else to approach this using the Dialogue System for Unity.
2) I have yet to really explore this option, as I have been stuck on the Auto button/ toggle.
If you could provide any insight as to whether my idea can work, please let me know. Or if you could find a better/ more efficient method, any tips on that would be great as well.
Many thanks in advance!
Re: Auto/ Skip buttons?
Hi,
[Auto Button]
I may need some more clarification from you. The Dialogue System's default behavior is to automatically continue one dialogue entry after another. Two things can halt this flow:
1. If the Dialogue Manager's Continue Button mode is set to wait for a continue button click.
2. Or if it's waiting for a player response. The Dialogue System will wait for a player response if the only valid responses are PC responses (i.e., no NPC responses). If there is only one valid PC response and the Dialogue Manager's Input Settings > Always Force Response Menu checkbox is unticked, it will automatically choose the response and bypass the menu.
Is your concern that either of the occurrences above will stop the automatic flow? If so, please let me know which one(s). I'll describe how to address it.
For the AudioWait() command, your current file structure is this:
Change it to this:
You can have as many Resources folders as you want in your project.
[Skip Button]
For the skip button, don't bother ticking the Dialogue System's 'SimStatus' checkbox. You'll need to use the script I outlined in my previous reply. I'll present a more detailed version below:
When you want to skip, set the script's skipAlreadyReadLines bool to true.
[Auto Button]
I may need some more clarification from you. The Dialogue System's default behavior is to automatically continue one dialogue entry after another. Two things can halt this flow:
1. If the Dialogue Manager's Continue Button mode is set to wait for a continue button click.
2. Or if it's waiting for a player response. The Dialogue System will wait for a player response if the only valid responses are PC responses (i.e., no NPC responses). If there is only one valid PC response and the Dialogue Manager's Input Settings > Always Force Response Menu checkbox is unticked, it will automatically choose the response and bypass the menu.
Is your concern that either of the occurrences above will stop the automatic flow? If so, please let me know which one(s). I'll describe how to address it.
For the AudioWait() command, your current file structure is this:
Code: Select all
Resources
Aria
Aria_1_37
Code: Select all
Aria
Resources
Aria_1_37
[Skip Button]
For the skip button, don't bother ticking the Dialogue System's 'SimStatus' checkbox. You'll need to use the script I outlined in my previous reply. I'll present a more detailed version below:
Code: Select all
using UnityEngine;
using System.Collections.Generic;
using PixelCrushers.DialogueSystem;
public class TrackLines : MonoBehaviour {
public bool skipAlreadyReadLines; // Tick in inspector to skip.
private List<string> hasRead = new List<string>();
private bool hasLoaded = false;
void Start() {
// When starting, load the list of lines that have already been read:
if (PlayerPrefs.HasKey("TrackLines")) {
hasRead = new List<string>(PlayerPrefs.GetString("TrackLines").Split(','));
}
hasLoaded = true;
}
void OnDestroy() {
// When exiting, save the list of lines:
if (hasLoaded)
{
PlayerPrefs.SetString("TrackLines", String.Join(",", hasRead.ToArray());
}
}
public void OnConversationLine(Subtitle subtitle) {
var lineID = subtitle.dialogueEntry.conversationID + ":" + subtitle.dialogueEntry.id;
if (hasRead.Contains(lineID)) {
if (skipAlreadyReadLines) {
subtitle.sequence = "None()"; // Already read, so skip.
}
} else {
hasRead.Add(lineID); // Record that this line has been read.
}
}
}
Re: Auto/ Skip buttons?
Hi Tony,
Once again, thank you for the quick reply. I will attempt to clarify the auto button a bit more.
Currently, I have my Dialogue System defaults set up such that it does not proceed automatically. It requires a continue button click after each node, and when there is a player response, it will pause the Dialogue accordingly. However, I would like to set up a toggle or button where, when clicked, it will essentially make it so that the continue button click is no longer required. This would apply to all text that is not a player response. However, as soon as the player makes their response, the no-continue button characteristic carries on until the player untoggles the auto function.
In essence, I would like to create a button or toggle (whichever works easier) that will allow the player to go between automatic and manual behaviour at will.
I hope this clears up a few things. Please let me know if you require further clarification! Thanks in advance!
Once again, thank you for the quick reply. I will attempt to clarify the auto button a bit more.
Currently, I have my Dialogue System defaults set up such that it does not proceed automatically. It requires a continue button click after each node, and when there is a player response, it will pause the Dialogue accordingly. However, I would like to set up a toggle or button where, when clicked, it will essentially make it so that the continue button click is no longer required. This would apply to all text that is not a player response. However, as soon as the player makes their response, the no-continue button characteristic carries on until the player untoggles the auto function.
In essence, I would like to create a button or toggle (whichever works easier) that will allow the player to go between automatic and manual behaviour at will.
I hope this clears up a few things. Please let me know if you require further clarification! Thanks in advance!
Re: Auto/ Skip buttons?
I think I understand. So the Auto button will essentially change the setting of the Dialogue Manager's Continue Button dropdown? If so, you could just have your button change that value. For example:
Code: Select all
DialogueManager.DisplaySettings.subtitleSettings.continueButton = DisplaySettings.SubtitleSettings.ContinueButtonMode.Never;