Search Unity

[RELEASED] Dialogue System for Unity - easy conversations, quests, and more!

Discussion in 'Assets and Asset Store' started by TonyLi, Oct 12, 2013.

  1. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,694
    Hi @katie-muller! Here's an example scene: SelectEnemyExample_2017-04-22.unitypackage

    I set the Sequence to this:
    Code (sequencer):
    1. None()@Message(EnemySelected)
    And added the script below to the enemies. It uses OnMouseUp() instead of a UI Button, but you could use the same idea with a UI Button. It sets a Dialogue System variable "Selection" to the name of the selected enemy, and then it sends the message "EnemySelected" to the sequencer:

    SelectableEnemy.cs
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using PixelCrushers.DialogueSystem;
    4.  
    5. public class SelectableEnemy : MonoBehaviour
    6. {
    7.     void OnMouseUp()
    8.     {
    9.         DialogueLua.SetVariable("Selection", name);
    10.         Sequencer.Message("EnemySelected");
    11.     }
    12. }
     
    katie-muller likes this.
  2. katie-muller

    katie-muller

    Joined:
    Feb 18, 2014
    Posts:
    18
    That makes sense! I'm learning more and more about how powerful this asset is every day I use it. It feels so nice to finally get rid of that dreaded "Go!" button, it was hindering my game flow for a while haha.

    As a follow up question, now that I have the "Go!" response removed, I would still like to have the "Nevermind" response available (cancels the selection). But since the Sequence prevents the conversation from continuing until I click on an enemy, I'm not sure how I can make that particular response display anyway! =(

    I'll attach a picture. I have "Nevermind" attached to "Who's my target?". Now I just need to find a way to force "Nevermind" to display.

    Thank you for all the help, as always!

    Capture.PNG
     
  3. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,694
    Hi @katie-muller! Here's an updated example scene: SelectEnemyExample_2017-04-23.unitypackage

    This isn't the only way you could do it, but here's what I did in the example:

    Changed the Sequence to:
    Code (sequencer):
    1. SetActive(Nevermind,true);
    2. SetActive(Nevermind,false)@Message(EnemySelected)
    This activates the GameObject (button) named "Nevermind". Then it waits for the EnemySelected message and deactivates the GameObject. In the Script field, set the Selection variable to an empty string:
    Code (Lua):
    1. Variable["Selection"] = ""
    I added this script to the Nevermind button so I could configure it to send the EnemySelected message:

    SendSequencerMessage.cs
    Code (csharp):
    1. using UnityEngine;
    2.  
    3. public class SendSequencerMessage : MonoBehaviour {
    4.     public void SendToSequencer(string message) {
    5.         PixelCrushers.DialogueSystem.Sequencer.Message(message);
    6.     }
    7. }
    If the conversation continues with an empty string in Selection, you know the player clicked Nevermind.
     
    katie-muller likes this.
  4. katie-muller

    katie-muller

    Joined:
    Feb 18, 2014
    Posts:
    18
    Oh, I see! That makes sense. I added the button to my scene and have everything working as you described =) Just as a curiosity, since you mentioned there are different ways of doing this, is there a way to make that "Nevermind" response appear as a response instead of as a seperate button? Only because I think it being a response will flow better with my game logic. For some reason, the "Nevermind" button is making it so Pokey's next dialogue (the "Whatever. You know where I am" node) is skipped over and the conversation ends, even when I add an Delay to his conversation node. The scripts in "Nevermind" fire though, so it's definitely going down that path. It's okay if no, though! I can make the button appear as a response =p

    Oh! Also, I'm getting some debug errors from this node after I added your Variable["Selection"] = "" script to my Nevermind node. Maybe that is why Pokey's next dialogue is skipping?

    Capture.PNG
     
  5. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,694
    What if you just add the Nevermind button as a regular, non-response button placed inside the response menu panel? Keep it inactive, and leave the activation to the SetActive() sequencer commands I mentioned above.

    Also, looks like your Conditions and Script fields are swapped.
     
    katie-muller likes this.
  6. katie-muller

    katie-muller

    Joined:
    Feb 18, 2014
    Posts:
    18
    I did just that! But for some reason, placing the button in the Response Menu made it so it could never be enabled. I ended up placing it outside of the Response Menu and messing around to make it look like a Response as best as I could. Now everything works the way it should =) Thank you very much, Tony!
     
  7. NeatWolf

    NeatWolf

    Joined:
    Sep 27, 2013
    Posts:
    924
    Hi Tony!

    I'm writing you here because it's a thing that may be useful to everyone. Possibly even a feature.

    Where's the best, safest place or what's the best practice to increase the duration of a node sequence when it's a leaf in the tree node?

    In other words: using fixed-length dialogue durations ( Delay(<fixed_value>) ) in the default-defaultplayer, I'd like to add an extra, fixed delay to the last sentence of a dialogue, whether if the last node is spoken by the player or not.

    Maybe its use would be too specific to integrate it with the base engine, but definitely it's not a rare scenario.
    Having an extra sequence to be executed only on the end leaves of a dialogue (differentiating between player, default, etc.) would be nice.

    In the meanwhile, which methods should I be overriding and how should I check if a node is a leaf? I read something in the docs about doing checks about future nodes 2 nodes before. Is this the case?

    Instead of overriding the sequence, I was thinking about chaining an extra delay, since otherwise I'd have to calculate the duration of the delay parsing the sequence text. Or using more variables.

    Could you please provide some advice or guidance about this?

    Thanks for your time, as usual :)

    Best,
    Alex
     
    katie-muller likes this.
  8. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,694
    Hi @katie-muller - Sorry about steering you wrong on that. The Dialogue System deactivates the Response Menu's panel except when it's in response menu mode. This would hide any custom UI elements inside the Response Menu panel during subtitle mode. The solution is exactly what you did.

    Hi @NeatWolf - If you want to add a delay to any leaf node programmatically at runtime, you can use an OnConversationLine method. Check if the subtitle is a leaf. If so, add a Delay() command:
    Code (csharp):
    1. public class AddSequenceToLeafNodes : MonoBehaviour {
    2.  
    3.     public string sequenceToAdd = "Delay(2)@{{end}};";
    4.  
    5.     void OnConversationLine(Subtitle subtitle) {
    6.         if (subtitle.dialogueEntry.outgoingLinks.Count == 0) {
    7.             subtitle.sequence = sequenceToAdd + subtitle.sequence;
    8.         }
    9. }
    Put this script on your Dialogue Manager GameObject. The Dialogue System will invoke OnConversationLine before showing the subtitle and playing the sequence. The method checks if the dialogue entry has any outgoing links. If not, it adds to the sequence. In the example above, it adds "Delay(2)@{{end}}" which means to delay 2 extra seconds after {{end}} seconds have passed. (The value of {{end}} is based on the length of the dialogue text.)

    There's one case in which this won't work: If the dialogue entry has outgoing links but all their conditions are currently false. Ideally, you would be able to check DialogueManager.CurrentConversationState, which contains a list of valid outgoing links (based on evaluating their conditions). Currently, the Dialogue System sets DialogueManager.CurrentConversationState after invoking OnConversationLine. The logic was to not set CurrentConversationState until the conversation had fully transitioned into that state by playing the subtitle and sequence. I'll look into the possibility of setting CurrentConversationState before invoking OnConversationLine. This will allow you to check the list of valid outgoing links, not just all outgoing links as defined at design time.
     
  9. NeatWolf

    NeatWolf

    Joined:
    Sep 27, 2013
    Posts:
    924
    Thanks Tony!

    Does this mean "end" in the logic meaning, or "end" as in after the default time based on the calculation of characters per seconds has passed? Can I use the expression both with fixed length and variable length node durations?

    I currently only have conditions near the root, and always very far from the end of the convo, so luckily is not my case :)
    But, when I read that part, that wasn't really immediate. Yet, making the checks before the checks are supposed to be done could lead to unexpected consequences if in the meantime something changes the results of the conditions.
    I believe that it could get tricky to the point of accepting what is already there as the best reasonable solution :)

    Thanks again for the timely and clear answer :)

    Best,
    Alessandro
     
  10. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,694
    Hi Alessandro - The latter. By {{end}} I mean the special keyword whose value is based on the length of the Dialogue Text and the Dialogue Manager's Display Settings > Subtitle Chars Per Second and Min Subtitle Seconds.

    If your dialogue entry nodes have sequences that are longer than {{end}}, I have two recommendations. You could make your OnConversationLine method a little fancier. For example, if the sequence is:
    Code (sequencer):
    1. AudioWait(hello)
    You'll want OnConversationLine to change it to something like:
    Code (sequencer):
    1. AudioWait(hello)->Message(Done);
    2. Delay(2)@Message(Done)
    This makes the AudioWait() command send a sequencer message "Done" when it's done. Then it adds a Delay(2) that doesn't start until it receives the sequencer message "Done". It just takes some minor text checking, something like:
    Code (csharp):
    1. void OnConversationLine(Subtitle subtitle) {
    2.     if (subtitle.dialogueEntry.outgoingLinks.Count == 0) {
    3.         subtitle.sequence = subtitle.sequence.TrimEnd(@" \n;");
    4.         return string.IsNullOrEmpty(subtitle.sequence) ? "Delay(2)@{{end}}"
    5.             :  subtitle.sequence + "->Message(Done); Delay(2)@Message(Done)";
    6.     }
    7. }

    Another approach, which I think I prefer, is to forget about OnConversationLine entirely, and just override the dialogue UI's HideSubtitle() and Close() methods. In HideSubtitle(), check if this is the last line. If so, delay before hiding. Something like this:
    Code (csharp):
    1. public class MyDialogueUI : UnityUIDialogueUI {
    2.  
    3.     private bool canClose = true;
    4.  
    5.     public override void HideSubtitle(Subtitle subtitle) {
    6.         var isLastLine = DialogueManager.CurrentConversationState != null && !DialogueManager.CurrentConversationState.HasAnyResponses;
    7.         if (isLastLine) {
    8.             StartCoroutine(DelayedHide());
    9.         } else {
    10.             base.DelayedHideSubtitle(subtitle);
    11.         }
    12.     }
    13.  
    14.     private IEnumerator DelayedHideSubtitle(Subtitle subtitle) {
    15.         canClose = false;
    16.         yield return new WaitForSeconds(2);
    17.         base.HideSubtitle();
    18.         canClose = true;
    19.         Close();
    20.     }
    21.  
    22.     public override void Close() {
    23.         if (canClose) base.Close();
    24.     }
    25. }
     
  11. Gua

    Gua

    Joined:
    Oct 29, 2012
    Posts:
    455
    Hm... I'm looking at inventory systems on the market and all of them seems too complex for my needs. So I'm wondering, how easy it is to appropriate dialogue system to serve as a simple shop and inventory?
     
  12. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,694
    Hi @Gua! The Dialogue System can handle the back-end data since the dialogue database has a section for Items. However, it doesn't provide an inventory UI, which is where most of the work of building an inventory system goes. If you inventory needs are very simple, you could build your own UI. Of the inventory systems that the Dialogue System provides integration packages for, S-Inventory and Inventory Master are the simplest to set up. The integration package for Inventory Master (which is free) isn't in the Third Party Support folder; it's on the Dialogue System Extras page.
     
  13. NeatWolf

    NeatWolf

    Joined:
    Sep 27, 2013
    Posts:
    924
    Hi Tony, thanks for the tips but none of the methods seems to work. I already have the "fading response" custom UI class using TMPro, and I tried to adapt it with the suggestions, but nothing seems to affect the default duration.

    Or, the condition of "being a leaf" never triggers, or is checked too late.
    There are a few oversights in the code you posted but I suppose those were not the problem.
    I could also move the default "delay" sequences inside the custom class, just defining the durations as floats there (2.7 secs for the default, 2 for the player default, plus a certain amount if the sentence is the last of the dialogue. In this way I don't have to do any weird string slicing but just format a single Delay(<calculated total delay>) for each scenario.

    Here's the code I'm using, there are some leftovers as I'm still experimenting:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using PixelCrushers.DialogueSystem.TextMeshPro;
    4. using PixelCrushers.DialogueSystem;
    5.  
    6. /// <summary>
    7. /// This subclass of TextMeshProDialogueUI keeps the response menu visible
    8. /// after the player clicks a response, but fades out all but the clicked
    9. /// button and makes them all non-interactive. The response button should
    10. /// have a CanvasGroup component. I used a CanvasGroup instead of an
    11. /// Animator because a bug in Unity UI prevents Buttons from playing nicely
    12. /// with Animators on the same GameObject.
    13. /// </summary>
    14. public class FNSDialogueUI : TextMeshProDialogueUI
    15. {
    16.  
    17.     public float responseFadeDuration = 0.7f;
    18.     public float delayAfterResponseFade = 0.7f;
    19.     public float lastSentenceExtraDelay = 3f;
    20.  
    21.     protected GameObject clickedButtonGO = null;
    22.     //protected bool canClose = true;
    23.  
    24.     public virtual void RecordClickedButton(GameObject buttonGO)
    25.     {
    26.         clickedButtonGO = buttonGO;
    27.     }
    28.  
    29.  
    30.     public override void HideSubtitle(Subtitle subtitle)
    31.     {
    32.         if (subtitle.speakerInfo.IsNPC)
    33.             return;
    34.      
    35.         base.HideSubtitle(subtitle);
    36.     }
    37.  
    38.     /*protected virtual IEnumerator DelayedHideSubtitle(Subtitle subtitle) {
    39.         canClose = false;
    40.         yield return new WaitForSeconds(lastSentenceExtraDelay);
    41.         base.HideSubtitle(subtitle);
    42.         canClose = true;
    43.         Close();
    44.     }*/
    45.  
    46.     /*public void OnConversationLine(Subtitle subtitle) {
    47.         if (subtitle.dialogueEntry.outgoingLinks.Count == 0)
    48.         {
    49.             //float _delay()
    50.          
    51.          
    52.             //subtitle.sequence = subtitle.sequence.TrimEnd(" \n;");
    53.             subtitle.sequence = string.IsNullOrEmpty(subtitle.sequence) ? ""//string.Format("Delay({0})@{{end}}", lastSentenceExtraDelay)
    54.                 :  subtitle.sequence + string.Format("->Message(NormalDelayComplete); Delay({0})@Message(NormalDelayComplete)", lastSentenceExtraDelay);
    55.         }
    56.     }*/
    57.  
    58.     public override void Close()
    59.     {
    60.         //if (canClose)
    61.         //{
    62.             dialogue.npcSubtitle.SetActive(false);
    63.             base.Close();
    64.     //}
    65.     }
    66.  
    67.     public virtual bool CurrentDialogueIsOnLastLine()
    68.     {
    69.         return DialogueManager.CurrentConversationState != null
    70.             && !DialogueManager.CurrentConversationState.HasAnyResponses;
    71.     }
    72.  
    73.     /*public override void ShowSubtitle(Subtitle subtitle)
    74.     {
    75.         base.ShowSubtitle(subtitle);
    76.         if (subtitle.speakerInfo.IsNPC
    77.             && CurrentDialogueIsOnLastLine())
    78.         {
    79.             subtitle.sequence = string.Format("Delay ({0})", 2f +lastSentenceExtraDelay);
    80.             //restore button alpha
    81.             //dialogue.responseMenu.Hide();
    82.             //dialogue.responseMenu.DestroyInstantiatedButtons();
    83.         }
    84.     }*/
    85.  
    86.     public override void HideResponses()
    87.     {
    88.         // Don't actually hide the responses right away.
    89.         // Instead, hide the subtitle reminder:
    90.         dialogue.responseMenu.subtitleReminder.Hide();
    91.      
    92.         // And then fade out all responses except the clicked one,
    93.         // and make them all non-interactive:
    94.         foreach (var tmp in dialogue.responseMenu.buttons)
    95.         {
    96.             GameObject buttonGO = tmp.gameObject;
    97.             var button = buttonGO.GetComponent<UnityEngine.UI.Button>();
    98.             if (button != null)
    99.             {
    100.                 button.interactable = false;
    101.             }
    102.             if (buttonGO != clickedButtonGO && buttonGO.activeInHierarchy)
    103.             {
    104.                 StartCoroutine(FadeCanvasGroup(buttonGO.GetComponent<CanvasGroup>()));
    105.             }
    106.         }    
    107.     }
    108.  
    109.     public override void ShowResponses(Subtitle subtitle, Response[] responses, float timeout)
    110.     {
    111.         base.ShowResponses(subtitle, responses, timeout);
    112.      
    113.         StopAllCoroutines();
    114.      
    115.         dialogue.responseMenu.buttons[0].GetComponent<CanvasGroup>().alpha = 1;
    116.         dialogue.responseMenu.buttons[1].GetComponent<CanvasGroup>().alpha = 1;
    117.     }
    118.  
    119.     /*protected virtual IEnumerator HideAndRestoreResponses()
    120.     {
    121.         yield return new WaitForSeconds(2);
    122.      
    123.         dialogue.ResponseMenu.Hide();
    124.         clickedButtonGO = null;
    125.     }*/
    126.  
    127.     protected IEnumerator FadeCanvasGroup(CanvasGroup canvasGroup)
    128.     {
    129.         if (responseFadeDuration > 0)
    130.         {
    131.             float elapsed = 0;
    132.             while (elapsed < responseFadeDuration)
    133.             {
    134.                 if (canvasGroup == null) yield break; // May not exist or may get destroyed by next NPC line.
    135.                 canvasGroup.gameObject.SetActive(true);
    136.                 canvasGroup.alpha = Mathf.Min(canvasGroup.alpha, 1 - elapsed / responseFadeDuration);
    137.                 yield return null;
    138.                 elapsed += Time.deltaTime;
    139.             }
    140.         }
    141.         if (canvasGroup != null) canvasGroup.alpha = 0;
    142.      
    143.         yield return new WaitForEndOfFrame();
    144.      
    145.         yield return new WaitForSeconds(delayAfterResponseFade);
    146.      
    147.         /*bool isLastLine = DialogueManager.CurrentConversationState != null
    148.             && !DialogueManager.CurrentConversationState.HasAnyResponses;*/
    149.      
    150.         /*if (CurrentDialogueIsOnLastLine())
    151.             yield return new WaitForSeconds(lastSentenceExtraDelay);*/
    152.      
    153.         dialogue.ResponseMenu.Hide();
    154.         clickedButtonGO = null;
    155.     }
    156. }
    157.  

    As it is now it works as it did before and as it should. Exception made for the extra delay that I can't seem to properly insert there. Even if I uncomment certain parts, I see no change. In the inspector the variable for the extra delay (lastSentenceExtraDelay) is set to 3 seconds. I have full logging and still I can only see sequences of Delay (2) or Delay(2.7) going on.

    Do you have any clue?
     
  14. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,694
    Hi Alessandro - I'll test out some code and reply back here later today. Since you're already overriding the dialogue UI, that's definitely the simplest way to go. It should only take a few extra lines of code, but I want to test it to make sure I don't type any typos in my reply.
     
  15. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,694
    Hi Alessandro - I think a couple things needed to be fixed in the code I had previously just typed into a reply. Here's a working example with the fixed script: FNSExtraDelayAtEnd_2017-04-25.unitypackage

    I'll paste the script below, too. I named it FNSDialogueUIExtraDelay.cs to prevent conflicts with your existing script.
    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using PixelCrushers.DialogueSystem.TextMeshPro;
    4. using PixelCrushers.DialogueSystem;
    5.  
    6. /// <summary>
    7. /// This subclass of TextMeshProDialogueUI keeps the response menu visible
    8. /// after the player clicks a response, but fades out all but the clicked
    9. /// button and makes them all non-interactive. The response button should
    10. /// have a CanvasGroup component. I used a CanvasGroup instead of an
    11. /// Animator because a bug in Unity UI prevents Buttons from playing nicely
    12. /// with Animators on the same GameObject.
    13. /// </summary>
    14. public class FNSDialogueUIExtraEndDelay : TextMeshProDialogueUI
    15. {
    16.  
    17.     public float responseFadeDuration = 0.7f;
    18.     public float delayAfterResponseFade = 0.7f;
    19.     public float lastSentenceExtraDelay = 3f;
    20.  
    21.     protected GameObject clickedButtonGO = null;
    22.     protected bool canClose = true;
    23.     protected Coroutine fadeCanvasGroupCoroutine = null;
    24.  
    25.     public virtual void RecordClickedButton(GameObject buttonGO)
    26.     {
    27.         clickedButtonGO = buttonGO;
    28.     }
    29.  
    30.     public override void HideSubtitle(Subtitle subtitle)
    31.     {
    32.         var isLastLine = DialogueManager.CurrentConversationState != null && !DialogueManager.CurrentConversationState.HasAnyResponses;
    33.         if (isLastLine)
    34.         {
    35.             if (canClose) StartCoroutine(DelayedHideSubtitleAndClose(subtitle));
    36.         }
    37.         else
    38.         {
    39.             base.HideSubtitle(subtitle);
    40.         }
    41.     }
    42.  
    43.     private IEnumerator DelayedHideSubtitleAndClose(Subtitle subtitle)
    44.     {
    45.         canClose = false;
    46.         Debug.Log("Waiting 2 extra seconds...");
    47.         yield return new WaitForSeconds(2);
    48.         Debug.Log("...done waiting! Closing dialogue UI.");
    49.         base.HideSubtitle(subtitle);
    50.         canClose = true;
    51.         Close();
    52.     }
    53.  
    54.     public override void Close()
    55.     {
    56.         if (canClose) base.Close();
    57.     }
    58.  
    59.     public override void HideResponses()
    60.     {
    61.         // Don't actually hide the responses right away.
    62.         // Instead, hide the subtitle reminder:
    63.         dialogue.responseMenu.subtitleReminder.Hide();
    64.  
    65.         // And then fade out all responses except the clicked one,
    66.         // and make them all non-interactive:
    67.         foreach (var tmp in dialogue.responseMenu.buttons)
    68.         {
    69.             GameObject buttonGO = tmp.gameObject;
    70.             var button = buttonGO.GetComponent<UnityEngine.UI.Button>();
    71.             if (button != null)
    72.             {
    73.                 button.interactable = false;
    74.             }
    75.             if (buttonGO != clickedButtonGO && buttonGO.activeInHierarchy)
    76.             {
    77.                 fadeCanvasGroupCoroutine = StartCoroutine(FadeCanvasGroup(buttonGO.GetComponent<CanvasGroup>()));
    78.             }
    79.         }
    80.     }
    81.  
    82.     public override void ShowResponses(Subtitle subtitle, Response[] responses, float timeout)
    83.     {
    84.         base.ShowResponses(subtitle, responses, timeout);
    85.  
    86.         if (fadeCanvasGroupCoroutine != null) StopCoroutine(fadeCanvasGroupCoroutine);
    87.  
    88.         foreach (var button in dialogue.responseMenu.buttons)
    89.         {
    90.             button.GetComponent<CanvasGroup>().alpha = 1;
    91.         }
    92.     }
    93.  
    94.     protected IEnumerator FadeCanvasGroup(CanvasGroup canvasGroup)
    95.     {
    96.         if (responseFadeDuration > 0)
    97.         {
    98.             float elapsed = 0;
    99.             while (elapsed < responseFadeDuration)
    100.             {
    101.                 if (canvasGroup == null) yield break; // May not exist or may get destroyed by next NPC line.
    102.                 canvasGroup.gameObject.SetActive(true);
    103.                 canvasGroup.alpha = Mathf.Min(canvasGroup.alpha, 1 - elapsed / responseFadeDuration);
    104.                 yield return null;
    105.                 elapsed += Time.deltaTime;
    106.             }
    107.         }
    108.         if (canvasGroup != null) canvasGroup.alpha = 0;
    109.  
    110.         yield return new WaitForEndOfFrame();
    111.  
    112.         yield return new WaitForSeconds(delayAfterResponseFade);
    113.  
    114.         dialogue.ResponseMenu.Hide();
    115.         clickedButtonGO = null;
    116.     }
    117. }
     
    NeatWolf likes this.
  16. longroadhwy

    longroadhwy

    Joined:
    May 4, 2014
    Posts:
    1,551
  17. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,694
  18. Hormic

    Hormic

    Joined:
    Aug 12, 2014
    Posts:
    251
    Hey TonyLi,

    A scenario in my game could be that on some triggers Tutorial Boxes are appearing.
    In between there could be a normal Dialog with an NPC and also maybe a narrator voice occasionally.
    All 3 with different UI Styles.
    So, what would you suggest is the best method to make a tutorial or respectively the above scenario working?

    Thank you very much for suggestions. :)
     
  19. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,694
    Hi @Hormic - Use Override Dialogue UI, or Override Display Settings if you want to override more than just the dialogue UI. (Note that you can also override most display settings such as continue button mode and default sequence by inspecting a conversation's properties in the Dialogue Editor.)

    For example, add an Override Dialogue UI component to your tutorial box trigger and point it to your tutorial box dialogue UI.
     
    Hormic likes this.
  20. Hormic

    Hormic

    Joined:
    Aug 12, 2014
    Posts:
    251
    That was fast, ok thank you,
    Is it possible to assign a unique UI to a different Char inside the actor settings?
    This would be the easiest way i guess.
     
  21. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,694
    No, sorry, because the UI could be located in a specific scene. Typically the actor has a GameObject in a scene. Add an Override Dialogue UI to that GameObject, and assign the UI there.
     
    Hormic likes this.
  22. Demonoid74

    Demonoid74

    Joined:
    Jan 20, 2017
    Posts:
    16
    Hello ,

    I just finally picked this up...have been watching it for awhile now and with the sale , just couldn't pass this up...
    I love what I have seen done with this and know it will work for everything I need it to . Just started messing around with Unity a few months back and haven't programmed anything since back in the Amiga PC days...its been awhile ;) So still have a lot to learn , even though most things are coming along nicely...with the little time I have to work on it between work and family...

    My project has advanced far enough along where I want to start setting up dialogue and quests etc. I did the quick start and tutorial and have a basic idea of how all to get it to work . Placed a dialogue manager into my project , have a UI working for it , ran the player wizard for my 1st person character and the npc wizard on a test conversation . It works and the npc reacts when I am in range...BUT...it still is allowing my character to move and look around , and interferes with clicking on the conversation options . The player wizard under custom controls and disable gameplay components only turns off the Selector script .

    I am using the Unity First Person character for my project with just some minor changes to it so far . Ideally while the project is running if I click off the first person controller script it works perfectly...now how do I get it to turn that script off instead of the Selector script...or with the selector script if must be...or whatever has to be done to get the desired effect!

    I eventually want to have the camera zoom in on the npc like in the examples...but for now , I just want to get it to work with disabling my movements ;) That I am sort of impatient about and want to try and get it done first...the rest , I am willing to go slow and learn how to set up the camera's and npc barks etc .

    Any help in getting that to work or a point in the right direction would be amazing!
     
  23. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,694
    Hi @Demonoid74 - Thanks for buying the Dialogue System!

    You can find step-by-step instructions (without using the wizard) in this post on the Pixel Crushers forum.

    Briefly, inspect your FPSController's Set Enabled On Dialogue Event component. Add the FirstPersonController component to its OnStart and OnEnd lists by creating increasing the size of each list and then dragging the FirstPersonController component's heading into the new slot. If you're using RigidBodyFPSController, also assign the MainCamera child's HeadBob component to both lists. (To assign HeadBob, you'll need to open 2 Inspector windows. Inspect FPSController in one, and click the lock icon at the upper right to keep the inspector on that GameObject. Then inspect HeadBob in the other.)

    If you didn't already, remember also to tick Show mouse cursor during conversations in the wizard, or add a Show Cursor During Conversation component, if you want to show the mouse cursor during conversations.

    If you get stuck on anything or have any other questions, just let me know!

    (BTW, for anyone using Unity's standard ThirdPersonController, the setup instructions are in the post above the I just linked. There's an extra step because of the way ThirdPersonController manages its animation.)
     
  24. strongbox3d

    strongbox3d

    Joined:
    May 8, 2012
    Posts:
    860
    Hello Toni,

    I am looking into buying your dialogue system. However I am working for Xbox One so I use a controller instead of Keyboard and mouse. How easy could be to change the input types in your system? Is that something that is part of your asset or it would require a lot of work?

    Regards,
    Carlos
     
  25. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,694
    Hi @strongbox3d - It's built in. On your Unity UI dialogue UI, just tick Auto Focus so the navigation starts on a button. This way the controller knows where to navigate from. Since the Unity UI dialogue UI uses Unity UI's EventSystem, it's also compatible with third party input systems like Rewired.

    Please feel free to try out the evaluation version and let me know if you have any other questions.
     
  26. strongbox3d

    strongbox3d

    Joined:
    May 8, 2012
    Posts:
    860
    Tony,

    Thanks for your quick response. I have my own Control system because of specs specific to XBO, so I don't use the EventSystem from Unity nor I use Rewired. My concern was more about how difficult the task of remapping your asset's default input to a controller's input could be. But I guess that trying it is the best way to find out.

    Regards,
    Carlos
     
  27. Demonoid74

    Demonoid74

    Joined:
    Jan 20, 2017
    Posts:
    16
    Just got home from work and after eating , loaded up my project and tried that out...it worked perfectly...I did not even notice the elements to increase the size etc. Would have been fumbling around for days probably even though it was right there in front of me lol

    Thanks for the super fast response and the solution to that problem! So far set up two extremely long branching conversations and they work perfectly now . Should be easy to put in things like knocking on a door , reading a gravestone , sign etc.

    Will mess with customizing the UI and camera focusing later on . Looking forward to experimenting and messing with this asset more and seeing what I can get it to do!
     
  28. Hormic

    Hormic

    Joined:
    Aug 12, 2014
    Posts:
    251
    Hey TonyLi thank you very much this works fine,
    but i have 2 other questions regarding the narrator or tutorial text.
    First question is,
    Is it neccesary to have an empty gameobject in the scene view, cause there is no need for an NPC in this case?

    Second Question is that the controls and camera movement are freezed when a conversation starts, which is fine when talking to a normal NPC, but in this case the control should not be affected. (I'm using RFPS.). So how can i adjust DS to not take the controls in the Tutorial and narrative Monologs? Maybe i have to disable the components on the player char - Set enable on Dialog and Set active on Dialog Event and so on?
     
  29. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,694
    Sounds good! The Dialogue System is designed to be UI-independent. For example, you can provide your own implementation of the C# interface IDialogueUI, and the Dialogue System will work happily with it. It's not tied to any specific input or output system. The only exception is the Dialogue Manager's Cancel and Cancel Conversation triggers; they assume Unity input, but this post explains how to use your own input system instead.

    Great! Glad I could help!

    For the Tutorial and monologues, assign GameObjects other than the player to the Conversation Trigger's Actor or Conversant field. This way the player won't receive the OnConversationStart and OnConversationEnd events that make it pause control. (It can be useful to use empty GameObjects for this purpose.) For example:
    1. Create a Tutorial GameObject.
    2. Add a Conversation Trigger, and set it to OnStart.
    3. Assign the Tutorial GameObject itself to the Actor and Conversant fields.
    4. Optionally, define a Boolean variable in your database called something like "CompletedTutorial". On the Conversation Trigger, set the Condition so that CompletedTutorial must be false. In the last node of the tutorial conversation, set CompletedTutorial true.
     
  30. NeatWolf

    NeatWolf

    Joined:
    Sep 27, 2013
    Posts:
    924
    Thanks Tony!
    I was wondering if you had time to look into the issue these days, but it appears you answered right on the same day and I missed the notification. I went here just to check if I misunderstood something about what you said last time and found a reply :)

    Thanks, I'm going to try it right now :)
     
  31. RandAlThor

    RandAlThor

    Joined:
    Dec 2, 2007
    Posts:
    1,293
    Can i use this also with the latest articy:draft 3.x.x ?
    If so can i use articy:draft´s export to unity or how will i do it the best (maybe still like in your video)?
    Can i use articy:draft´s multilanguage feature to import to your asset?
    (Will i am able to use quest´s from a:d in your new quest system?)
     
    Last edited: Apr 29, 2017
  32. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,694
    Hi @RandAlThor - Yes, the Dialogue System works with all versions of articy:draft 1.x through 3.x. It does not require Nevigo's articy plugin for Unity. Just export to XML and import into the Dialogue System as shown in the video.

    Nevigo never actually implemented multilanguage support inside articy:draft. Instead, for articy:draft 3.x they created a localization plugin that generates an empty localization template as an Excel spreadsheet that you can fill in outside of articy. Over the past week, I've been implementing support for the localization plugin into the next version of the Dialogue System's articy importer. I'm also adding support for their new voiceover plugin, too.

    (Side note: Since articy's XML format has supported multilanguage from 2.x, the Dialogue System has been able to import it. The problem was that articy:draft itself doesn't provide a way to enter multilanguage text in its editor. Some people wrote their own third party utilities to post-process the XML file to add their multilanguage translations before importing into the Dialogue System, which was what Nevigo recommended prior to their localization plugin.)

    Yes. articy import won't be in the beta release of Quest Machine, but it's a priority to add as soon as possible.
     
    Hormic likes this.
  33. RandAlThor

    RandAlThor

    Joined:
    Dec 2, 2007
    Posts:
    1,293
    Great, thank you for your fast answer.
    Did not know of the voiceover plugin :)
     
  34. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,694
    It's pretty neat because it can automatically generate text-to-speech audio files for testing until you get real voice actors to record the lines. I'm trying to get a beta download of the next Dialogue System version onto the customer download page by the end of this weekend so people can test out the plugin support.
     
  35. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,694
    Just passing along something handy that occurred to me. You can use [var=varName] and [lua( luacode )] tags in your sequences. Another way to express the sequencer command above is:

    Delay([lua( {{end}} + 2 )])

    You could just as easily use a Dialogue System variable:

    Delay([lua( {{end}} + Variable["userDefinedExtraDelay"] )])
     
  36. JACKO4590

    JACKO4590

    Joined:
    Nov 25, 2014
    Posts:
    81
    Hi TonyLi.
    On your Dialogue Menu System you have a music manager.
    I put a clip in the box and used the audio Source thats on the menu system but its not playing. is there a function for it to play? or do i have to call it manually and stop it once leaving the menu?
     
  37. Lethn

    Lethn

    Joined:
    May 18, 2015
    Posts:
    1,583
    Thanks for making this asset, it's actually exactly the sort of thing Unity needs for RPGs and so on. I recently bought this and I'm playing around with it, all the tutorials are straight forward but unless I'm just being blind I can't seem to find anything on making incrementing text?

    Is there an option somewhere that allows me to enable this that I've missed? I do of course mean that JRPG/Zelda style dialogue that goes character by character rather than simply popping up the whole line.
     
  38. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,694
    Hi @JACKO4590 - On the Dialogue System Extras page, the latest version of the Menu Framework (updated 4/30) automatically plays the Music Manager's title music in the title scene. It also has methods to stop music and play other music.

    Hi @Lethn - Thanks for buying the Dialogue System! It includes a pretty sophisticated typewriter effect that supports sounds, RPG Maker-style pause codes, and more. To see it in action, play the scene Examples / Unity UI Examples / Generic UI Example Scene.
     
  39. strongbox3d

    strongbox3d

    Joined:
    May 8, 2012
    Posts:
    860
    Hello Tony,

    I have been looking into converting the input of your asset S-Quest, from pc input to my Xbox One controllers input on the evaluation version I downloaded, and I can't find how to do that. I have all my input manager mapped to my controller. The problem is that I don't see where I can make for example: the response selection of a dialogue use my left thumbpad up/down to select an answer, and in general to use my mapped input manager. That's the only thing stopping me from buying the full version of the asset. Could you please advice me on how to do this?

    Regards,
    Carlos
     
  40. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,694
    Hi @strongbox3d - I recommend using Unity UI and writing a small, custom input module that uses your input manager instead of Unity's input manager as the Standalone Input Module does. The Unity UI source code is here in case you want to see how the built-in input modules work. If you're familiar with Rewired, you'd implement it similarly to how Rewired implements its Rewired Standalone Input Module. This way you get all the advantages of Unity UI and the Dialogue System's extensive Unity UI Dialogue UI system.
     
  41. strongbox3d

    strongbox3d

    Joined:
    May 8, 2012
    Posts:
    860
    Hello Tony,

    I am not familiar with Rewired and I am using Unity's input manager to set my control's input buttons including the Thumbstick, triggers, ect. All my UI is made using the new Unity UI already. What I need is to be able to direct your Asset's input to use the data in Unity's input manager where everything is set already. If that is possible, I need some guide to do so, and I will be ready to buy the asset, since I can figure out everything else.

    Regards,
    Carlos
     
  42. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,694
    Hi Carlos, I'm not sure I understand yet. The Dialogue System doesn't do any input directly (with this small exception I mentioned previously).

    If your dialogue UI uses the Unity UI Dialogue UI component, it will use the Unity UI EventSystem. The Unity UI Dialogue UI doesn't care what kind of input module is behind the EventSystem (e.g., standard Unity input, Rewired, your own custom controller, etc.). My previous reply contains information about how to write a Unity UI input module for your own custom controller if that's what you need to do.

    If your dialogue UI doesn't use the Unity UI Dialogue UI component yet -- for example, if you've set up the UI elements but haven't connected them to any Dialogue System components yet -- then you can use this video tutorial to add a Unity UI Dialogue UI component and assign your UI elements to it. The Unity UI Dialogue UI manual page has much more information about features and configuration.

    If that doesn't help, please feel free to post screenshots of where you're at, or email a copy of your project to tony (at) pixelcrushers.com and let me know what version of Unity to use. I'll be happy to take a look.
     
  43. strongbox3d

    strongbox3d

    Joined:
    May 8, 2012
    Posts:
    860
    Hello Tony,

    I don't use the Unity input event system because I am developing for Xbox One and went took a different route for inputs handling. This is what I have set up right now: I am using the "Letterbox Unity UI Dialogue UI" from your prefabs, I have set up a dialogue between my "PC" and a "NPC" character. Now the problem is that when I move to the Npc, and start the conversation, the Npc ask a question to the Pc, at which point the Pc has two possible answers, the first one is lighted in yellow as default and the seconds answer is white. the problem is that when I move the left thumbstick down or up it should switch the selection between the 2 answers but it doesn't. Neither pressing my A button in the control, selects the highlighted response text to continue the dialogue, as it should. However I have this buttons set in the input manager in Unity and they work with everything else.

    For example if I write the code: if(input.GetAxis("The name I set in the input manager for this axis"))
    {
    DoSomething();
    }
    This works everywhere. Now where is the "DoSomething() type of method in your asset so I can alter the input on"?

    Regards,
    Carlos
     
    Last edited: May 1, 2017
  44. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,694
    There is no DoSomething() type of method in the Dialogue System. The Letterbox Unity UI Dialogue UI relies on Unity UI's navigation system to switch the selection. It's just standard Unity UI, with no custom selection code in the Dialogue System. The Unity UI EventSystem needs at least one input module, such as the Standalone Input Module:



    The Standalone Input Module's Vertical Axis specifies the name set in the Unity input manager for this axis. Try changing this from "Vertical" to the name that you set.
     
  45. strongbox3d

    strongbox3d

    Joined:
    May 8, 2012
    Posts:
    860
    Hello Tony,

    I did the above and nothing happened. I believe that is because it is missing the "condition" in the "Dialogue Entry". How is the "condition" added to the Dialogue entry, for say: when button "Fire1" is pressed, continue to "X" entry. See screen grab for illustration.

    Regards,
    Carlos DialogueSystem.jpg
     
  46. strongbox3d

    strongbox3d

    Joined:
    May 8, 2012
    Posts:
    860
  47. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,694
    Hi @strongbox3d - In some areas, I will admit the Dialogue System is a little complex. However, in this regard, it's much simpler than what you're asking. You can leave all of the Conditions and Script fields blank for now. They are not used for UI navigation. They are only used to determine which nodes to show, typically based on variable values.

    Inspect your dialogue UI, and make sure Auto Focus is ticked:



    This will select the first response when showing a response menu. Then, Unity UI will navigate up or down through the responses based on XboxOneVertical. When A is pressed, it will click the current selection. The navigation and clicking is all handled through Unity UI, not the Dialogue System.
     
  48. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,694
    Deftly, Makinom, Rog, RT-Voice, RPG Kit, & ICode Updated Support Packages Available

    The Dialogue System Extras page has updated support packages for Makinom, RT-Voice, RPG Kit 3.1.7 and ICode. It also has a new integration package for Rog, which is a neat little turn-based roguelike framework, and a preliminary package for Deftly that I believe is feature complete but I'm still soliciting feedback on.
     
    LaneFox likes this.
  49. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,694
    An/Other - Now in WebGL

    Please check out Jordan Sparks' An/Other, which uses the Dialogue System and was just updated to run in WebGL. This project on Games For Social Change has been featured in The Toronto Star, The Torontoist, Metro News, CityNews Toronto, and the radio program Mediation Station, and has been exhibited at several seminars and conferences.



    If you're interested in games for social change, in addition to playing the game you can also read Sparks' 80-page research paper. (He recommends playing the game fully before reading the paper.)
     
  50. Demonoid74

    Demonoid74

    Joined:
    Jan 20, 2017
    Posts:
    16
    Hey again ,

    Have had a chance to mess around with it only for a few hours here and there . Have basic and long branching conversations set up all around my town and a few NPC's doing random barks . So far it is doing everything I want and need this asset to do .

    I have come across a few things I can not get to work that I would love to know how or if possible . I have lots of houses around my small town . I have it set up to the majority of non important locations to have a conversation start when you knock on the door and wanted it to have random responses . I have a few nodes branching off from the last one at the end . 6 nodes so far that I put linked to the last line of the generic knocking on door conversation I set up...but , every single time it always picks the top response...how would I go about having it actually randomly pick from those responses? I don't want to use random barks...which I can get to work...because I want it to hold the player in place till the responses are done .

    Also is there anyway to trigger a sound at a specific line of dialogue? such as having a knocking sound on one line , a few lines later have a door creaking open noise play etc.

    The other thing , is there a way to limit how far away a bark is visible? as of now I can be across the street and behind a house and still see the NPC's random barks going off .