Search Unity

  1. We are migrating the Unity Forums to Unity Discussions. On July 12, the Unity Forums will become read-only.

    Please, do not make any changes to your username or email addresses at id.unity.com during this transition time.

    It's still possible to reply to existing private message conversations during the migration, but any new replies you post will be missing after the main migration is complete. We'll do our best to migrate these messages in a follow-up step.

    On July 15, Unity Discussions will become read-only until July 18, when the new design and the migrated forum contents will go live.


    Read our full announcement for more information and let us know if you have any questions.

Official Dialogue System + Timeline track

Discussion in 'Open Projects' started by MachairaJP, Oct 1, 2020.

  1. MachairaJP

    MachairaJP

    Joined:
    Jan 31, 2014
    Posts:
    30
    I'd like to give this a shot. 15u should be pretty easy and quick. 15s a bit more so. :)
     
  2. cirocontinisio

    cirocontinisio

    Joined:
    Jun 20, 2016
    Posts:
    884
    Hey @MachairaJP, sounds good. How are you imagining it?

    By the way, I renamed the thread to make it a bit more related to the cards, in the interest of making it official later on. Let's kick off the discussion! :)
     
  3. Aspekt1024

    Aspekt1024

    Joined:
    Sep 29, 2016
    Posts:
    12
    Hey, I'd like to collaborate on this one in conjunction with the Cutscene system. I made a cutscene system for another game with a dialogue track, and would really like to improve my skills on this.

    The
    DialogueTrack
    itself allows addition of
    DialoguePlayableAssets
    . In our game these were grouped into multiple lines spoken by different characters, and could all be placed along the track similar to individual animations that marked the start (when the dialogue started showing) and end (when the dialogue stopped showing, and optionally pausing the Timeline) of the line of dialogue. The dialogue system itself controlled the display of dialogue, and accepting player input to progress the dialogue.
    dialogueTrack.png
     

    Attached Files:

  4. MachairaJP

    MachairaJP

    Joined:
    Jan 31, 2014
    Posts:
    30
    I'm assuming we want something like this:

    https://easygamewalkthrough.com/wp-...r-Kokiri-sword-hidden-somewhere-in-Forest.png

    were words can be highlighted in a color, since that was mentioned in the card and UI to move to the next dialog item. I'm also assuming we don't need multiple choices for questions the NPC might ask, just something like Yes/No UI? I'm not quite sure how you're envisioning timelines to be used with a dialog system. This could all just be done with UI elements and script.

    I'm guessing a scriptable object representing a dialog would just be attached to the NPC and the dialog would be played when the player interacts with that NPC. Would more than one dialog be attached to an NPC and played in sequence conditionally based on what the player has done? Fetch quest, kill something quest, etc.? If so, we'd have to have a way to query the player gameobject to see if it's fulfilled the quest.
     
  5. Aspekt1024

    Aspekt1024

    Joined:
    Sep 29, 2016
    Posts:
    12
    Hey @MachairaJP I made a skeleton implementation of the Dialogue Track here: https://github.com/Aspekt1024/open-project-1/tree/cutscene

    Very happy to hear any feedback and improvements on this implementation.

    The key scripts are in Assets/Scripts/Cutscene/DialogueTrack. It allows a Dialogue Scriptable Object to be referenced in each Dialogue Playable Asset (an item in the DialogueTrack), or added directly to the timeline via an existing Dialogue SO. The attached image shows what this looks like in the timeline. I didn't attempt to create the Dialogue system, but did create something for the Dialogue Track to feed into.

    @theabhinv The Cutscene Manager is the entry point for playing cutscenes. The one I've implemented is only really for demonstration purposes and to start some conversation about how it might work.

    I have a sample (Scenes/Cutscene) that demonstrates how this might work in-game :)
     

    Attached Files:

    Neonage likes this.
  6. Neonage

    Neonage

    Joined:
    May 22, 2020
    Posts:
    288
    This one is great! Does it allow to make delay between sentences?
     
  7. Aspekt1024

    Aspekt1024

    Joined:
    Sep 29, 2016
    Posts:
    12
    It definitely can, and is ultimately dependent on how the dialogue system works, in that the Dialogue SO could have a single line of dialogue, or multiple that get acknowledged before the dialogue is complete. In either case, it would work like this:
    • Timeline triggers dialogue
    • Dialogue system requested to play from referenced Dialogue SO
    • In the case of multiple lines, player input will cycle through all lines of dialogue until complete
    • If the Asset in the Dialogue Track reaches its end and the player hasn't acknowledged the dialogue, the timeline pauses, otherwise it keeps playing
    • Once dialogue has been acknowledged by the player, the timeline resumes
    It would also be easy to auto-progress the dialogue if multiple lines are given in a Dialogue SO by adding a counter to the DialoguePlayableBehaviour's ProcessFrame
     
    Neonage likes this.
  8. dkaloger

    dkaloger

    Joined:
    Jul 7, 2019
    Posts:
    39
    hi I am also interested i think we should use a csv format so it is very easy to add new things and also not need to have multiple files for the same chat or monologue .we could also use tags e.g #greentext or #wavy
     
  9. dkaloger

    dkaloger

    Joined:
    Jul 7, 2019
    Posts:
    39
    also how can we collaborate to make a cohesive mechanic and avoid overlap .will we use the cutscene branch?
     
    Last edited: Oct 2, 2020
  10. MachairaJP

    MachairaJP

    Joined:
    Jan 31, 2014
    Posts:
    30
    So I looked at your branch project and I guess I'm having trouble envisioning how a timeline makes the dialog system easier. It seems like it's more complicated as it's an extra piece that's involved.

    Normally a simple trigger on the NPC is sufficient to kick off the dialog. The dialog system takes care of the rest. In the case of a cutscene, if you're using a timeline it can invoke the dialog system when it's needed. The dialog system shouldn't know anything about the timeline however.

    Using a timeline feels like shoehorning a system in that's not needed. Just my opinion. :)
     
  11. MachairaJP

    MachairaJP

    Joined:
    Jan 31, 2014
    Posts:
    30
    In this case scriptable objects is a nice compromise. The individual dialog items can be tweaked without tying up the entire dialog and there's no parsing that's needed to read the dialog. I would say the SO items for each dialog could be in their own folders under a Dialogs folder in the Assets for easy organization.
     
  12. dkaloger

    dkaloger

    Joined:
    Jul 7, 2019
    Posts:
    39
    i have started working and already been able to display sentences from a csv (separated by . )
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using TMPro;
    5. using System.IO;
    6.  
    7. public class DialogueRendererer : MonoBehaviour
    8. {
    9.   [SerializeField]  private TextMeshProUGUI Text;
    10.   [SerializeField] string[] sentences;
    11.   [SerializeField] int sentence;
    12.     private int DefaultDelay = 5;
    13.     // Start is called before the first frame update
    14.     void Start()
    15.     {
    16.         Text = gameObject.GetComponent<TextMeshProUGUI>();
    17.         StartCoroutine(NewChat("Assets/Dialogue/1.csv"));
    18.     }
    19.  
    20.     // Update is called once per frame
    21.     void Update()
    22.     {
    23.         //  Text.text = System.IO.File.ReadAllText("Assets/Dialogue/1.csv");
    24.         //  chat = System.IO.File.ReadAllText("Assets/Dialogue/1.csv").Split("/"[0]);
    25.  
    26.  
    27.     }
    28.     IEnumerator NewChat(string directory)
    29.     {
    30.         sentences = System.IO.File.ReadAllText(directory).Split("."[0]);
    31.         for (int i = 0; i < sentences.Length ; i++)
    32.         {
    33.  
    34.             Text.text = sentences[sentence];
    35.             sentence++;
    36.             yield return new WaitForSeconds(DefaultDelay );
    37.        
    38.         }
    39.     }
    and then we could have another script that just calls this IEnumerator and only needs the name of the relevant text file btw this script works
     
  13. Neonage

    Neonage

    Joined:
    May 22, 2020
    Posts:
    288
    Dialogs are little cutscenes themselves, aren't they?
    We need to animate how text flows with characters expression and movement. We can't do this with simple trigger
     
  14. dkaloger

    dkaloger

    Joined:
    Jul 7, 2019
    Posts:
    39
    i think we should ask the writers and we can still apply effects (speed ,color ,bold,wavy)to text even without the timeline
     
  15. dkaloger

    dkaloger

    Joined:
    Jul 7, 2019
    Posts:
    39
    also new code that slowly writes the sentence
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using TMPro;
    5. using System.IO;
    6.  
    7. public class DialogueRendererer : MonoBehaviour
    8. {
    9.   [SerializeField]  private TextMeshProUGUI Text;
    10.   [SerializeField] string[] sentences;
    11.   [SerializeField] int sentence;
    12.     private float letterdelay = 0.2f;
    13.     private string displayed;
    14.     // Start is called before the first frame update
    15.     void Start()
    16.     {
    17.         Text = gameObject.GetComponent<TextMeshProUGUI>();
    18.         StartCoroutine(NewChat("Assets/Dialogue/1.csv"));
    19.     }
    20.  
    21.     // Update is called once per frame
    22.     void Update()
    23.     {
    24.         //  Text.text = System.IO.File.ReadAllText("Assets/Dialogue/1.csv");
    25.         //  chat = System.IO.File.ReadAllText("Assets/Dialogue/1.csv").Split("/"[0]);
    26.  
    27.  
    28.     }
    29.     IEnumerator NewChat(string directory)
    30.     {
    31.    
    32.         sentences = System.IO.File.ReadAllText(directory).Split("."[0]);
    33.         for (int i = 0; i < sentences.Length ; i++)
    34.         {
    35.             for (int t = 0; t < sentences[sentence].Length ; t++)
    36.             {
    37.                 Debug.Log(t);
    38.                 displayed += sentences[sentence][t];
    39.                 Text.text = displayed;
    40.                 yield return new WaitForSeconds(letterdelay);
    41.             }
    42.             sentence++;
    43.             displayed = "";
    44.  
    45.  
    46.  
    47.  
    48.  
    49.         }
    50.     }
    51. }
     
  16. dkaloger

    dkaloger

    Joined:
    Jul 7, 2019
    Posts:
    39
    final code for tonight
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using TMPro;
    5. using System.IO;
    6.  
    7. public class DialogueRendererer : MonoBehaviour
    8. {
    9.   [SerializeField]  private TextMeshProUGUI Text;
    10.   [SerializeField] string[] sentences;
    11.   [SerializeField] int sentence;
    12.     private float letterdelay = 0.2f;
    13.     private string displayed;
    14.     private Color color;
    15.    public string color_string;
    16.     // Start is called before the first frame update
    17.     void Start()
    18.     {
    19.         Text = gameObject.GetComponent<TextMeshProUGUI>();
    20.         StartCoroutine(NewChat("Assets/Dialogue/1.csv"));
    21.     }
    22.  
    23.     // Update is called once per frame
    24.     void Update()
    25.     {
    26.         //  Text.text = System.IO.File.ReadAllText("Assets/Dialogue/1.csv");
    27.         //  chat = System.IO.File.ReadAllText("Assets/Dialogue/1.csv").Split("/"[0]);
    28.  
    29.  
    30.     }
    31.     IEnumerator NewChat(string directory)
    32.     {
    33.    
    34.         sentences = System.IO.File.ReadAllText(directory).Split("."[0]);
    35.         for (int i = 0; i < sentences.Length ; i++)
    36.         {
    37.             findtag(sentences[sentence]);
    38.           ColorUtility.TryParseHtmlString(color_string.TrimStart('#'), out color);
    39.             Text.color = color;
    40.        
    41.             for (int t = 0; t < sentences[sentence].Replace(color_string, "").Length ; t++)
    42.             {
    43.                 Debug.Log(t);
    44.                 displayed += sentences[sentence].Replace(color_string, "")[t];
    45.                 Text.text = displayed;
    46.                 yield return new WaitForSeconds(letterdelay);
    47.             }
    48.             sentence++;
    49.             displayed = "";
    50.  
    51.  
    52.  
    53.  
    54.  
    55.         }
    56.     }
    57.     void findtag(string sentence)
    58.     {
    59.         for (int i = 0; i < sentence.Length; i++)
    60.         {
    61. if(sentence[i].ToString() == "#")
    62.             {
    63.                 while (sentence[i].ToString() != " ")
    64.                 {
    65.                     color_string += sentence[i].ToString();
    66.                     i++;
    67.                 }
    68.  
    69.             }
    70.         }
    71.     }
    72. }
     
  17. dkaloger

    dkaloger

    Joined:
    Jul 7, 2019
    Posts:
    39
    @Aspekt1024 i sent pull request with my changes
     
  18. MachairaJP

    MachairaJP

    Joined:
    Jan 31, 2014
    Posts:
    30
    Not necessarily, no.

    Do we? I didn't see that anywhere in the card.

    I'm of the "simpler is better" mindset here. A simple dialog system like the screenshot I posted should be fine. We don't even necessarily need to animate the text being displayed.
     
  19. MachairaJP

    MachairaJP

    Joined:
    Jan 31, 2014
    Posts:
    30
    That's great, except the card calls for using scriptable objects.
     
  20. dkaloger

    dkaloger

    Joined:
    Jul 7, 2019
    Posts:
    39
    o
    ohh uhhh can we ask them if we cn use csv or txt files
    i honestly think it works better
     
  21. Neonage

    Neonage

    Joined:
    May 22, 2020
    Posts:
    288
    We're making open-source game right there, not freelancing with strict tasks only.
    Anyone can imagine a great new thing that will make the game better and bring it to life

    Simple is better != feature poor.
    Simple is better = complex, yet made in the way that is easy to understand and work with, without limiting capabilities.
    And that all about Timeline. It gives us all the power and ability to easily intergate our dialogs inside cutscenes.

    I don't want our game to feel plain and unemotional, just because someone said that it would be simpler to make.
    Even slight adjustment in the dialog animation can make it feels more emotional
     
  22. dkaloger

    dkaloger

    Joined:
    Jul 7, 2019
    Posts:
    39
    an example of the dialogue formatting :
    [john] hello world #yellow. [mark]*bold#yellow hello.
     
    Last edited: Oct 2, 2020
  23. Neonage

    Neonage

    Joined:
    May 22, 2020
    Posts:
    288
    It doesn't support Unity serialisation and we would not be able to integrate these txts into Timeline or events logic.
    Parsing full text at runtime is the worst practice.
    There is no way we can use it.
    ScriptableObject already giving us all we want, and if you want tags - Text Mesh Pro supports them nicely
     
  24. dkaloger

    dkaloger

    Joined:
    Jul 7, 2019
    Posts:
    39
    it is ,much quicker to add new dialogue without timelines
     
  25. dkaloger

    dkaloger

    Joined:
    Jul 7, 2019
    Posts:
    39
    ok i will start working on a scriptable object based solution
     
  26. Neonage

    Neonage

    Joined:
    May 22, 2020
    Posts:
    288
    What do you imagine by dialogue?
    For me it's an animated conversation between player and NPC (where camera and characters are already handled by Timeline), not a spawn of plain text by trigger
     
  27. dkaloger

    dkaloger

    Joined:
    Jul 7, 2019
    Posts:
    39
    well just some text in the bottom slowly revealing some animations not related to the conversation basically like animal crossing
     
  28. dkaloger

    dkaloger

    Joined:
    Jul 7, 2019
    Posts:
    39
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. [CreateAssetMenu(fileName = "Conversation", menuName = "ScriptableObjects/Conversation", order = 1)]
    4. public class conversation : ScriptableObject
    5. {
    6.     public sentence[] lines;
    7.  
    8. }
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using TMPro;
    5. using System.IO;
    6.  
    7. public class DialogueRendererer : MonoBehaviour
    8. {
    9.   [SerializeField]  private TextMeshProUGUI Text;
    10.   [SerializeField] string[] sentences;
    11.   [SerializeField] int sentence;
    12.     private float letterdelay = 0.2f;
    13.     private string displayed;
    14.  
    15.    public string color_string;
    16.     public conversation conversation;
    17.  
    18.     void Start()
    19.     {
    20.         Text = gameObject.GetComponent<TextMeshProUGUI>();
    21.         StartCoroutine(NewChat("Assets/Dialogue/1.csv"));
    22.     }
    23.  
    24.  
    25.     IEnumerator NewChat(string directory)
    26.     {
    27.  
    28.  
    29.         for (int i = 0; i < conversation.lines.Length ; i++)
    30.         {
    31.        
    32.             Text.color = conversation.lines[sentence].color;
    33.             Text.fontStyle = (FontStyles)conversation.lines[sentence].fontstyle;
    34.    
    35.             for (int t = 0; t < conversation.lines[sentence].text.Length ; t++)
    36.             {
    37.                 Debug.Log(t);
    38.                 displayed += conversation.lines[sentence].text[t];
    39.                 Text.text = displayed;
    40.                 yield return new WaitForSeconds(letterdelay);
    41.             }
    42.             sentence++;
    43.             displayed = "";
    44.         }
    45.     }
    46.  
    47. }
    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. [Serializable]
    6. public class sentence
    7. {
    8.     public string text;
    9.     public Color color;
    10.     public FontStyle fontstyle;
    11. }
    12.  
    is this ok? i will clean the code up later can you do your timeline stuff with this
     
  29. dkaloger

    dkaloger

    Joined:
    Jul 7, 2019
    Posts:
    39
    ok i made it work with timelines
     
  30. Aspekt1024

    Aspekt1024

    Joined:
    Sep 29, 2016
    Posts:
    12
    Hey all, just to clarify, the Dialogue Track is only meant to be for cutscenes. The dialogue system is intentionally separate for this reason, so it can be triggered in game by talking to an NPC as @MachairaJP is planning, or via Timeline in the cutscene system.

    The cutscene system is a separate task that I believe @theabhinv will be looking into, and the Timeline track ties the two together.

    Once the dialogue system is roughly in place I can finish the first implementation of the dialogue track for cutscenes :)
     
  31. MatasVa

    MatasVa

    Joined:
    Jan 12, 2015
    Posts:
    1
    Hey, I am a bit confused about the different types of "Dialogue" we are planning to implement.
    As I understand currently, the player approaches an NPC, the camera perspective shifts and the dialogue begins, with the player being able to select different dialogue options and the conversation being animated with the timeline.

    Is my understanding correct? If so, are there any other "Dialogues" you guys have in mind?

    Cheers!
     
  32. dkaloger

    dkaloger

    Joined:
    Jul 7, 2019
    Posts:
    39
    probably no any choice just a conversation ,apart from the timeline the dialogue is nearly done
    and i think the timeline is a very bad idea that has little benefit and makes creating new dialogue much much harder
     
  33. cirocontinisio

    cirocontinisio

    Joined:
    Jun 20, 2016
    Posts:
    884
    Wow, lots of conversation in here! Ok this is the way I see it, and obviously open to feedback:

    Dialogues are series lines of text displayed in balloons or on a UI at the bottom of the screen. The player can advance them by pressing a button (for story bits), or sometimes they go away on their own (for a character screaming "hey!").

    So n.1: we need a data container for these lines. I believe it should be an SO.

    Obviously dialogues should have a concept of chaining, so you can sequence multiple lines from different characters and if they are independent, it means we can build a small graph (branching answers?).

    As for the Timeline track, it would be a custom track that can at any time call for a line of dialogue. So you would have a clip on the timeline, and when the Timeline reaches that point the line of dialogue is displayed on screen. Depending on the options of this clip, the Timeline might pause, waiting for the user to press a button, or just keep going (i.e. the dialogue line is timed and disappears when the clip is over).

    I've actually demoed something of the kind years ago at Unite Austin:


    So the Timeline track has to hook into the dialogue system. The dialogue system however is completely independent.
    This would allow us to have simple dialogues and more complex cutscenes.

    How we trigger these two is irrelevant at the moment. They could be tied to a Prefab, there could be a more overarching "story manager", but for what I'm concerned, I'd start with a script in the scene that just goes "PlayDialogueLine" in Start :D

    This is how I imagine it, at least.
     
    Last edited: Oct 25, 2020
    Neonage likes this.
  34. fran_m

    fran_m

    Joined:
    Jul 22, 2020
    Posts:
    40
    The dialogues are gonna be multilanguage? I mean, the project will support localization?
     
  35. dkaloger

    dkaloger

    Joined:
    Jul 7, 2019
    Posts:
    39
    so i think i can finnish the dialogue sysem today but i have no idea about timeline integration
     
  36. dkaloger

    dkaloger

    Joined:
    Jul 7, 2019
    Posts:
    39
    so it is near completion i think i will do a pull request to master soon
     
  37. dkaloger

    dkaloger

    Joined:
    Jul 7, 2019
    Posts:
    39
    ok i thing apart from the timeline integration dialogue is done does anyone want to help do QA
     
  38. dkaloger

    dkaloger

    Joined:
    Jul 7, 2019
    Posts:
    39
    Last edited: Oct 3, 2020
  39. Aspekt1024

    Aspekt1024

    Joined:
    Sep 29, 2016
    Posts:
    12
    Hey thanks for the patience in waiting for my response - I'm in a timezone that's asleep while many others are active (GMT+10). I've accepted the CLA.

    Timeline integration can now be done relatively separate from the Dialogue system so imho we don't need to rush with that, and I'm happy to fix up the Timeline Track if, say, the public methods in the dialogue system change how dialogue is called for any reason :)
     
  40. dkaloger

    dkaloger

    Joined:
    Jul 7, 2019
    Posts:
    39
    you just need to run the ienumenerator in the dialogue renderer at the start of the first dialoge line then modify the i enumerator to accept the duration of currently played clip to decide on the letter delay (letterdelay = duration /conve3rsation.lines.length )
     
  41. dkaloger

    dkaloger

    Joined:
    Jul 7, 2019
    Posts:
    39
    i will start working on timeline integration with your help (i tried to do it before but i was really confused ,some minor fixes to allow multiple conversations ,code cleaning and maybe triggers that cn loop between multiple conversations
     
  42. dkaloger

    dkaloger

    Joined:
    Jul 7, 2019
    Posts:
    39
    and some clarification on how the conversations are structured ,
    conversations are the scriptable objects they hold an array of lines
    a line is a sentence it has many variables ,the text ,the portait of the person speaking,the override for their name it will use the name of the sprite if the overide is left empty ,and text effects
     
  43. dkaloger

    dkaloger

    Joined:
    Jul 7, 2019
    Posts:
    39
    and finally we need the help of d artist to meke the ui pretier and make some portraits

    ps: to trigger a conversation just walk near the round tree in cutscene scene
     
  44. dkaloger

    dkaloger

    Joined:
    Jul 7, 2019
    Posts:
    39
    do you know how to do localization
     
  45. michelepiccolini

    michelepiccolini

    Joined:
    Dec 30, 2019
    Posts:
    2
    Hey @cirocontinisio, I really love the Timeline that you showcased in your talk. Seems powerful and simple to use!
    Is the code you demoed publicly available somewhere?
    Thanks :)
     
  46. dkaloger

    dkaloger

    Joined:
    Jul 7, 2019
    Posts:
    39
  47. michelepiccolini

    michelepiccolini

    Joined:
    Dec 30, 2019
    Posts:
    2
  48. dkaloger

    dkaloger

    Joined:
    Jul 7, 2019
    Posts:
    39
    btw we need art

    ui(backround for subtitles ,and a maybe a outline for the portraits) ,custom font (we will need it to be animated as a spritesheet to create wavy text ) and some character portraits
     
  49. dkaloger

    dkaloger

    Joined:
    Jul 7, 2019
    Posts:
    39
    can we add the localisation package
     
  50. Caiuse

    Caiuse

    Joined:
    Jan 6, 2010
    Posts:
    30
    I've made a pull request to lay the foundations of this logic, https://github.com/UnityTechnologies/open-project-1/pull/64 I've not gone as far as to define the whole text on screen system but instead created a abstract class that can be inherited to define this at a later date.

    This introduces the concept of a dialog timeline track, which can have a DialogBinder ( the base class for settings the current line of dialog ). It also contains a DialogClip, each clip will assigned the `dialogLineID` to the binder when the clip starts, and when the clip stops it can conditionally pause the whole timeline graph.
     
    Last edited: Oct 4, 2020
    Aspekt1024 likes this.