Search Unity

[70% OFF - FLASH DEAL] 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,698
    I still owe you a small script. Your description of the timer handlers provided with the Dialogue System was spot on. But it's a small addition to make it work the way you described.

    And if any other questions come up, don't hesitate to ask here or in email to tony (at) pixelcrushers.com.
     
  2. RodzGames

    RodzGames

    Joined:
    Dec 9, 2014
    Posts:
    24
    Looks like I solved my problem by simply updating the Dialogue System to the latest version (1.5.6.1)
    (I should have done that sooner... Sorry!)

    But the updating brought another little problem.

    When the conversation end, the animator of the dialogue panel doesn't have time to do the hiding animation, it automatically disable the panel.
    I didn't have that problem before, is it a bug?

    Thanks again!
     
  3. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,698
    I see you're working on an Oculus game! If you're planning to use the Dialogue System for this, you may be interested in using world-space UI canvases such as World Space Dialogue UIs:



    While you could do this before version 1.5.7, an additional checkbox and component in 1.5.7 makes it much easier. This version hasn't been posted on the Asset Store yet. If you'd like access to the Pixel Crushers customer download site to get it now, just PM me your Asset Store invoice number.

    Hi @Matrix456 - I'll take a look at this and get back to you with any settings that you might need to adjust on your dialogue UI.
     
  4. silentslack

    silentslack

    Joined:
    Apr 5, 2013
    Posts:
    394
    OK, success with the button position. A little bit of a pain to do that by text rather than a handy little enum but it works :) thanks!

    Again, the em works but would be better if I could just change the default colour in a single place rather than for every response?

    Couple more!
    - Can I dynamically change the Timeout time? Some questions require a little more thinking than others. I see the DialogueSystem script come from a dll, does this stop me from editing the variable at runtime?
    - Just being able to chose the correct response based on current selection but I'm hoping new script will solve that one!?

    Thanks for the help :)

    p.s Yes, I'm already using a floating menu from the OculusRift example package (downloaded that from your site I think?).
     
  5. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,698
    @Matrix456 - Doh, sorry, that was a bug! It was a simple one line fix. You can download the updated Unity UI Support package here or on the Extras page.

    @silentslack - On the button's Unity UI Response Button component, set the Default Color.

    Download and import the updated Unity UI Support package. It also includes a new sequencer command, SetTimeout(#), that you can use to change the timeout value for subsequent response menus.

    Not at all. In your own code, you can change it with:
    Code (csharp):
    1. DialogueManager.DisplaySettings.inputSettings.responseTimeout = 42; // Your duration here.
    That's exactly what the SetTimeout(#) sequencer command does under the hood. BTW, if you ever do want to dig into the source, you can unpack it. The precompiled DLLs significantly speed up your compile times, though.

    This seemed like such a useful one that I put it in the Unity UI Dialogue UI script itself. There's a new checkbox in the Response Menu section named Select Current On Timeout. If you tick this, it will select the currently-highlighted response button if the timer reaches zero.

    In fact, here's an example scene that does exactly that: TimedGamepadExample_2015-11-02.unitypackage

    It looks like this:


    It's hardly a beauty pageant winner, but it just took a couple minutes to put together. Here are some random notes:
    • The "X" response button's Default Color is blue. Responses that use this button will be blue unless they override the color with [em] tags.

    • I added UI Button Key Trigger components to the four response buttons. I assigned the keyboard keys A, B, X, & Y, but I did not assign button names. To do this, define the button names in Unity's Input Manager and then add them to the UI Button Key Triggers' Button Name fields.

    • I did kind of a haphazard navigation setup. In your real UI, you'll want to give a little more attention to how your buttons' Navigation is set up.

    • On the dialogue UI, I set Button Alignment to First. If you don't specify a response's position, it will fill in the gaps in the order A, B, X, then Y. I also ticked Select Current On Timeout and Auto Focus.

    • To play the NPC's typewriter effect while the response menu comes up, I moved it to the NPC Subtitle Reminder Line. The NPC's dialogue entries finish immediately (e.g., None() instead of Delay({{end}}) in their Sequence fields), so all the player sees is the subtitle reminder instead.

    • On the Dialogue Manager, I set Response Timeout to 5. In the NPC's second question in the example database, I used SetTimeout(10) to increase the timeout duration.

    • A couple responses use explicit [position #] tags in their Menu Text. The rest just fill in the buttons where they can.
     
  6. silentslack

    silentslack

    Joined:
    Apr 5, 2013
    Posts:
    394
    @TonyLi that is really great, exactly the dialogue system I had in mind so really awesome that your system is flexible enough to handle this :)

    I'm having a slight issue however. I would like it so that pressing A, B, X or Y doesn't select your response, it merely highlights it. Once the timer is up it then handles the selection. I understand that the new checkbox takes care of selecting the response, but how do I highlight a response in code? I'm currently generating a NullPointer at:
    Code (CSharp):
    1.                 var currentButton = UnityEngine.EventSystems.EventSystem.current.currentSelectedGameObject.GetComponent<UnityUIResponseButton>();

    I have set the ReponsButton default color to White and also on the Text object but continues to be black!? I have disabled a lot of the UI so maybe this is the problem? The only thing I want to show from the UI system are the Responses & Timer as I handle the pretty minimal UI myself:



     
  7. Candescence

    Candescence

    Joined:
    Aug 26, 2014
    Posts:
    107
    Again, thanks for the help on the scrollbar, and while I was fiddling around with stuff while preparing to send a log file, I noticed the log info in the debug list had a rather interesting bug that was actually the cause of the PC subtitle problems - turns out the current UI throws a fit if an actor doesn't have a portrait image. I could easily correct this with a null check, but that would be unnecessary and a waste of processing, since every subtitle should have a portrait anyway. So that's fixed now, too.

    Anyhow, no other problems so far, but I'll let you know if I have further issues I get stumped on.
     
  8. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,698
    Hi @Candescence - Great! Is the bug in the Dialogue System's UI code or your code? If it's in Dialogue System code, I'd like to fix it. Thanks!

    Hi @silentslack - The UIButtonKeyTrigger.cs script submits the response when you press the button. You could make a similar script called something like UIButtonKeyHighlighter.cs:
    Code (csharp):
    1. using UnityEngine;
    2.  
    3. public class UIButtonKeyTrigger : MonoBehaviour {
    4.  
    5.     public KeyCode key = KeyCode.None;
    6.     public string buttonName = string.Empty;
    7.  
    8.     private UnityEngine.UI.Button button = null;
    9.  
    10.     void Awake() {
    11.         button = GetComponent<UnityEngine.UI.Button>();
    12.         if (button == null) enabled = false;
    13.     }
    14.  
    15.     void Update() {
    16.         if (Input.GetKeyDown(key) || (!string.IsNullOrEmpty(buttonName) && Input.GetButtonDown(buttonName))) {
    17.             UnityEngine.EventSystems.EventSystem.current.currentSelectedGameObject = button.gameObject;
    18.         }
    19.     }
    20. }
    BTW, the line of code in your post that was raising the NullReferenceException should check that currentSelectedObject is non-null before trying to get components on it. As Unity UI and the Dialogue System both do their layout processes, currentSelectedObject may be null in some frames.


    Are you using [em] tags? Maybe the emphasis tag definitions are black.

    Clever solution to the VR locomotion problem! :)
     
  9. silentslack

    silentslack

    Joined:
    Apr 5, 2013
    Posts:
    394
    @TonyLi Thanks for the continued help.

    - UnityEngine.EventSystems.EventSystem.current.currentSelectedGameObject is read-only so can't be set? Is there any other way I can tell your system an option is highlighted?

    - Not using any EM tags. Really puzzled by that...

    Yes, walking really takes away the feeling of immersion for me and reminds me I'm playing a game. This works much better!
     
  10. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,698
    Oops, try EventSystem.SetSelectedGameObject():
    Code (csharp):
    1. UnityEngine.EventSystems.EventSystem.SetSelectedGameObject(button.gameObject, null);
    Maybe the Button component's Normal Color is black?
     
  11. Candescence

    Candescence

    Joined:
    Aug 26, 2014
    Posts:
    107
    I'm pretty sure it's just my code, but you can easily test it, the only condition is an actor not having any portrait images assigned whatsoever. Though, the fact that the Dialogue System throws the error rather than my script probably is a good indicator that it might be a bug in how DS handles portrait images.
     
  12. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,698
    Thanks for the info. I'll double check the Dialogue System code, but I suspect it's in your code and that the Dialogue System is just catching the error. Many of my test scenes have some actors without portrait images.
     
  13. silentslack

    silentslack

    Joined:
    Apr 5, 2013
    Posts:
    394
    Ok solved my issues. I use this for highlighting:

    Code (CSharp):
    1. EventSystem.current.SetSelectedGameObject(aButton.gameObject, null);
    As for the black font, it was because my Font Material was not set on the Label, it was blank for some reason.

    The only issue I'm having now (and looks to be the last!) is highlighting the default selected option. Is there an event or any way I would know which of my buttons is the default highlighted? Or what is the logic that picks the default and I can apply the same! Thanks!
     
  14. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,698
    Check UnityEngine.EventSystems.EventSystem.current.currentSelectedGameObject. If it's non-null, run GetComponent<UnityUIResponseButton>() on it.

    When the dialogue UI's Auto Focus checkbox is ticked, it highlights the first active response button. If you want to do something different, you could add a small script to the Dialogue Manager (or your player) that has an OnConversationResponseMenu() method:
    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using PixelCrushers.DialogueSystem;
    4. ...
    5. public UnityUIDialogueUI dialogueUI; // Assign in inspector or find at runtime.
    6.  
    7. void OnConversationResponseMenu(Response[] responses) {
    8.     StartCoroutine(HighlightResponseAfterFrame(responses));
    9. }
    10.  
    11. IEnumerator HighlightResponseAfterFrame(Response[] responses) {
    12.     // Wait one frame for the dialogue UI to set up the buttons:
    13.     yield return null;
    14.  
    15.     // Then highlight a button according to your custom rules:
    16.     // In this example, always highlight the third button:
    17.     var defaultButton = dialogueUI.dialogue.responseMenu.buttons[2];
    18.     EventSystems.EventSystem.SetSelectedGameObject(defaultButton.gameObject, null);
    19. }
     
  15. silentslack

    silentslack

    Joined:
    Apr 5, 2013
    Posts:
    394
    @TonyLi Thank you, thank you! Now we have the system I envisioned from the start. Thanks for all your help :) I'll make sure to review
     
  16. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,698
    Glad to help! Please feel free to send me links to a video or screenshots if you'd like a spot on the Dialogue System's Games Showcase page.
     
  17. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,698
    Check out Fourattic Games' Crossing Souls! It's a totally rad 1980's nostalgia-fest, and it uses the Dialogue System for Unity!



    You can still get in on the crowdfunding action right here.
     
    Teila likes this.
  18. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,698
    Updated RPG Kit 3.1.1 Support Package Available

    The Extras page has an updated RPG Kit 3.1.1 support package, which you can also download here: RPGKit_Support_2015-11-06.unitypackage

    The only additions are a preconfigured Loading scene and a small tweak to animation on the quest log window UI. You can use the preconfigured Loading scene by replacing RPG Kit's Loading scene in your project's build settings. This way you don't have to go through any steps to add and hook up the Dialogue System UI elements in the original Loading scene.
     
  19. iScream8

    iScream8

    Joined:
    Feb 16, 2015
    Posts:
    10
    Aww. Those world space dialogue uis will be cool for an augmented reality. T-T too bad I just learn it now. Anyway, I've been having a hard time looking for a script for playing the bark via script... Is it possible to play it on button press or something? I just thought that it'll be helpful so that the player can play the bark again?
     
  20. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,698
    Use them in your sequel! :)

    Hi @iScream8 - In script, just call DialogueManager.Bark(). For example, say you want to make Sergeant Graves bark:
    Code (csharp):
    1. var sgtGraves = GameObject.Find("Sergeant Graves").transform;
    2. DialogueManager.Bark("Sergeant Graves Barks", sgtGraves);
    In the Feature Demo, Sergeant Graves barks on his own at random times, but you can also "use" him (target him and hit the spacebar) to make him bark on demand. To set this up, I added a Usable component and a Bark Trigger set to OnUse.
     
  21. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,698
    Free Dialogue System Extras

    Many Dialogue System for Unity customers aren't aware that there's a page full of free extras:

    Dialogue System Extras

    It has all kinds of goodies such as:
    • Complete menu system (based on Unity's Game Jam Menu) with slot-based save and load
    • Choose Your Own Adventure framework
    • New sequencer commands
    • Quest and conversation examples for things like skill checks and multi-panel UIs for conversations that involve lots of characters
    • And plenty more
     
    BackwoodsGaming and hopeful like this.
  22. username132323232

    username132323232

    Joined:
    Dec 9, 2014
    Posts:
    477
    Sorry for a totally noob question, but what are advantages of using "Dialogue System for Unity" + "Adventure Creator" vs. just "Adventure Creator" which already has the ability to include conversations in ActionLists?
     
  23. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,698
    Hi @username132323232 - That's actually a great question. There are some feature differences. The Dialogue System for Unity lets you import content from articy:draft, Chat Mapper, Neverwinter Nights 1 & 2, and CSV spreadsheets. Some consider the Dialogue System's UI subsystem to be more customizable. And it has an integrated quest/mission system and other features that you might find useful. But, on the other hand, it's an additional product to get to know. Please feel free to look over the documentation, and if you have any questions, just let me know!
     
  24. username132323232

    username132323232

    Joined:
    Dec 9, 2014
    Posts:
    477
    Thanks Tony! Dialogue System is now on my short "to buy" list :)
     
    TonyLi likes this.
  25. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,698
    Updated Master Audio Support Package Available

    The Dialogue System Extras page has an updated support package for Master Audio v.3.5.8.7+, which introduced an API change to the AddToDucking method.

    The MAAddToDucking sequencer command now has two more optional parameters:

    MAAddToDucking(soundGroupName, riseVolumeStart, [duckedVolMult], [unduckTime])
    • soundGroupName: name of sound group
    • riseVolumeStart: percentage of sound played to start unducking
    • duckedVolMult: percentage of original volume. Default: 0.5.
    • unduckTime: amount of time to return music to original volume. Default: 1.
    You can also down the package directly here: MasterAudio_Support_2015-11-11.unitypackage
     
  26. alexhapki

    alexhapki

    Joined:
    May 8, 2015
    Posts:
    32
    Hi,
    I bought your Dialogue System and it has been very useful for a RPG game we are making. However I got a question. How can we save the Quest into from the QuestLog? I am using JRPG Unity GUI Quest Log Window. How can I save the quests into file and Load them later?
    Thank you in advance,
    Alex.
     
  27. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,698
    Hi @alexhapki - Use the Dialogue System's Save System. In brief, to save a game:
    Code (csharp):
    1. string saveData = PersistentDataManager.GetSaveData();
    This will get the values of the variables and quest states.Then write the saveData string to a file.

    Add a LevelManager script to your Dialogue Manager. To load a game, read the saveData string from the file. Then:
    Code (csharp):
    1. DialogueManager.Instance.GetComponent<LevelManager>().LoadGame(saveData);
    If you don't want to use LevelManager, you can call:
    Code (csharp):
    1. PersistentDataManager.ApplySaveData(saveString);
    But LevelManager provides lots of benefits, such as loading the same level that the game was saved in.

    The Dialogue System Extras page has a free menu framework that provides slot-based saving and loading. It's the first button under EXTRAS. By default, it saves to PlayerPrefs. To save to a local file, you just need to make a subclass of the included SaveHelper.cs script and override the load and save methods to work with local files.
     
    alexhapki likes this.
  28. alexhapki

    alexhapki

    Joined:
    May 8, 2015
    Posts:
    32
    Hi Tony,
    Brilliant! Thanks a million for that. It worked out perfectly and it is very simple! I am really impress.
    Just for everyone´s information what I did was to serialize the string saveData variable so I can save it on the slots (folder/filename) of my game system, and I just open it and use the DialogueManager.Instance.GetComponent<LevelManager>().LoadGame(saveData); to load it after deserializing. I pasted it below in case anyone is interested.
    Code (CSharp):
    1.     void SaveQuests ()
    2.     {
    3.         string mainPlayerName = gameController.GetComponent<GameController>().mainPlayerName;
    4.  
    5.         string fileName = @"C:/SaveGame/Quests.dat";
    6.  
    7.         saveData = PersistentDataManager.GetSaveData();
    8.        
    9.         Debug.Log (saveData);
    10.        
    11.         BinaryFormatter bf = new BinaryFormatter();
    12.        
    13.         FileStream file = File.Create(fileName);
    14.        
    15.         saveQuest data = new saveQuest();
    16.        
    17.         data.saveData = saveData;
    18.        
    19.         bf.Serialize (file, data);      
    20.        
    21.         file.Close ();
    22.     }
    and to load the Quests back with the same conditions than when it was saved;
    Code (CSharp):
    1.     void LoadQuests ()
    2.     {
    3.         string mainPlayerName = gameController.GetComponent<GameController>().mainPlayerName;
    4.        
    5.         string fileName = @"C:/SaveGame/Quests.dat";
    6.  
    7.         BinaryFormatter bf = new BinaryFormatter();
    8.         FileStream file = File.Open (fileName , FileMode.Open);
    9.         saveQuest data = (saveQuest) bf.Deserialize(file);
    10.         file.Close();
    11.        
    12.         saveData = data.saveData;
    13.        
    14.         DialogueManager.Instance.GetComponent<LevelManager>().LoadGame(saveData);
    15.        
    16.         Debug.Log (saveData);
    17.     }
     
    TonyLi likes this.
  29. alexhapki

    alexhapki

    Joined:
    May 8, 2015
    Posts:
    32
    ps. I expect to have beta version of the game by the end of summer 2016. So far so good, meeting plans / schedules. Once I have it ready and launch our website we will let people know we used your Dialogue System on the game. It is certainly of great help for any game. Thanks for the good work you do with Dialogue System.
     
  30. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,698
    Thank you for sharing the code above!

    If you'd like a spot on the Dialogue System's Games Showcase and a mention on the blog, please send me the URL when it's ready and a link to a video or screenshots.

    Best luck with the launch!
     
  31. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,698
    Animated Portraits in Unity UI Dialogue UIs

    The Unity UI Dialogue UI doesn't have built-in support for animated portraits yet. If you're interested in this feature, here's the candidate for the next release: UnityUIAnimatedPortraits_2015-11-11.unitypackage. It's also on the Extras page. It currently imports into Test/AnimatedPortraits, since it's not a final feature yet. It includes an example scene.

    Documentation will be in the final release. In brief:

    1. Add a Use Animated Portraits component to your dialogue UI.

    2. Add an Animated Portrait component to each actor.

    3. For each actor, create an animator controller that plays a spritesheet animation. Assign it to the actor's Animated Portrait.

    4. If you want to change the actor's "mood," you can use the AnimatorPlay or AnimatorTrigger sequencer commands to transition to a different state. For PCs, specify "PC Portrait Image" as the subject of the command. For NPCs, you'll want to duplicate the command and specify "NPC Portrait Image" and "NPC Reminder Portrait Image" as the subjects of the commands.
     
    Last edited: Nov 14, 2015
  32. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,698
    Updated RPG Kit Support Package Available

    The Dialogue System for Unity's RPG Kit Support package has been updated for RPG Kit 3.1.1 Lite and Full. You can download it on the Dialogue System Extras page. In addition to updating the package to support API changes in RPG Kit 3.1.1, it also includes a few UI tweaks for the dialogue and quest log UIs, and it automatically saves Dialogue System data (currently to PlayerPrefs) so your quest states, variable values, etc., will persist between play sessions.
     
  33. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,698
  34. Silent8Strike

    Silent8Strike

    Joined:
    Mar 10, 2014
    Posts:
    29
    Not sure if this has been answered previously, but how difficult would it be to use this system with a different audio engine?

    Our project is using Wwise for audio as we found Unity's audio system to be severely lacking at the time. This asset would save us quite a bit of work but only if we don't need to spend significant development time integrating Wwise.
     
  35. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,698
    Hi @Silent8Strike - It's easy but requires a tiny bit of scripting. The Dialogue System for Unity manages output such as audio using sequencer commands. It includes a template script for your own sequencer commands. You just copy the script and insert your code as described here, typically just a couple lines of code. This same template was used to write sequencer commands for Unity's built-in audio system and Dark Tonic's Master Audio. Other developers have done the same for Wwise, but I'm afraid they were in-house to those studios, so I don't have a copy to share. I can provide assistance if you have any questions integrating Wwise.
     
  36. Silent8Strike

    Silent8Strike

    Joined:
    Mar 10, 2014
    Posts:
    29
    Thanks for the quick reply, that's exactly what I needed to know.
     
  37. silentslack

    silentslack

    Joined:
    Apr 5, 2013
    Posts:
    394
    Hi, I've had a poke around and can't find an easy way to do this and hopefully it's an easy one to solve. Would like a way to pick up a 'WaitForMessage()' from script so I can then let my gameplay system know the dialogue system is waiting and make stuff happen!

    Is there an easy way to do this or do I need to SendMessage(), Wait(), then send message back?

    Thanks!
     
  38. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,698
    Hi @silentslack - No, I think the SendMessage() sequencer command is the way to go. Use it to send a 'WaitForMessage' message to your script, and then use the @Message sequencer syntax to wait for the reply from your script. For example:
    Code (sequencer):
    1. SendMessage(RunMarathon);
    2. Audio(Cheering)@Message(CrossedFinishLine)
    And then in your script:
    Code (csharp):
    1. void RunMarathon() {
    2.     //...do stuff...
    3.     Sequencer.Message("CrossedFinishLine");
    4. }
    Then again, if you're going to do this for more lines than not, consider adding an OnConversationLine method instead. This method can check the dialogue entry and decide whether it should do something and send the sequencer a message.
     
  39. silentslack

    silentslack

    Joined:
    Apr 5, 2013
    Posts:
    394
    OK awesome, I'll check that out. Thanks!
     
  40. silentslack

    silentslack

    Joined:
    Apr 5, 2013
    Posts:
    394
    Sorry to bother you again mate but I'm having a problem where my Database is becoming corrupted and I'm losing my dialogues and not sure why. It looks like the data is replaced by Hex:



    Have you seen anything like this before? I switch my PC off last night, opened it this morning and it was like this. This is the second time it has happened.
     
  41. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,698
    Hi @silentslack - Try setting serialization mode to Mixed. (Edit > Project Settings > Editor) If that doesn't help, try Force Text. It looks like Unity is having a serialization issue. I've seen this happen generally, not specific to the Dialogue System. A dialogue database is a plain old Unity ScriptableObject that uses Unity's built-in serialization. It doesn't do anything special. If you're seeing this with dialogue databases, you should spot check other assets in your project to make sure they're not also affected.

    Unity can serialize assets (ScriptableObjects, scene files, prefabs, etc.) in binary format or text format. When you see hex like that, it's usually because Unity is trying to deserialize a binary-format asset as text. The two cases where I've seen this happen are:

    1. Importing some older Unity 4.x 32-bit binary assets into Unity 5.x, which is 64-bit. This was due to a Unity bug with 32-bit to 64-bit conversion. This probably isn't the case in your project.

    2. Sharing a project (perhaps via version control like Subversion or Git) where one developer has set his or her serialization mode to Force Binary and the other has set it to Force Text, or some other conflicting combination like that.

    There could be other causes -- maybe a third party script that does some kind of project-wide processing when Unity starts up or shuts down?

    I'm sorry you lost dialogues. Few things suck like losing creative work. As a safeguard against data loss, in the future you can make text-based backup copies of your dialogue database by exporting it to Chat Mapper XML format. (Use the Dialogue Editor's Export Database feature.) Then you can use the Chat Mapper Converter to reimport your work from the XML copy it if you need to. Again, serialization issues tend to affect the whole project, not a single type of serialized file, so this will only provide some safety for dialogue databases, not for other asset types in your project. You'll want to get to the bottom of the serialization issue, too.
     
  42. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,698
    Updated RPG Kit Support Package Available

    The Dialogue System Extras has an updated support package for Unitycoding's RPG Kit (Lite and Pro versions). It adds:
    • Character-specific saving and loading of Dialogue System data (quest states, persistent data components, etc.)
    • "Update Quest Tracker" ICode action
    • RPG Kit Store Trigger No Out Of Range Message component. This is the same component as RPG Kit's Store Trigger except it doesn't show a "too far" message when you click on the NPC. Use it when you want to set the store trigger's distance to 0 to allow the RPG Kit Conversation Trigger to grab control first, like the example Converser NPC.
     
  43. maltakereuz

    maltakereuz

    Joined:
    Mar 29, 2015
    Posts:
    53
    Should i use one global dialogue DB in RPG?

    i am making an RPG-game, using dialogue system for unity. There is ~10 locatins in game and probably like 1000 dialogues. Now it's time to make some design considerations. At first i planned to use different Dialogue-DB for each locations. It's clearer. But now i am not sure. May be it's just easier to use just one global DB for all? So i can forget about transfering vairables from one DB to others and writing code to switch DB. I can use prefixes for different locations. Is there any performance problems? And what do you coonsider for adequat design using Dialogue-System-For-Unity in an RPG-game?
     
  44. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,698
    Hi @maltakereuz - A single database is easier to manage, but the Dialogue System is also designed to work nicely with multiple databases without having to do any scripting. Tortured Hearts uses the Dialogue System with about 70 databases encompassing 500,000 words of dialogue.

    Here's my recommendation:

    A dialogue database with 1000 average-length conversations might take about 15 MB of memory, or the equivalent of a handful of texture files.

    If you're making a desktop game, 15 MB shouldn't be a concern. In this case, the only reason to use multiple databases is for your organizational benefit.

    If you're building for low-end mobile devices, 15 MB might be too much. It really depends on your specs and requirements.

    Whether you use a single database or multiple, consider using forward slashes in conversation titles to group your conversations. For example, you could title your conversations:
    • Companions/Robot Butler
    • Desert/Scavenger
    • Desert/Scorpion Herder
    • Jungle/Shaman, etc.
    This will group them into submenus "Companions", "Desert", and "Jungle" in the Dialogue Editor, making it much easier to select conversations.

    If you decide to use multiple databases, here are some tips:

    Put all your global data in a global database, and assign this as the Dialogue Manager's Initial Database. This should include everything that needs to be in a saved game or accessible regardless of location, such as:
    • The Player actor and all actors that can cross locations, such as companions who follow the player around
    • Quests
    • Global variables
    • Conversations that can play regardless of where the player is, such as companion chatter
    In your other databases, use Sync From DB to sync in the global data content. This way you can reference global data in any database in the Dialogue Editor.

    You may or may not need to use the Unique ID Tool. Every dialogue database asset loaded into memory needs a unique ID for that asset type -- for example, every actor should have a unique actor ID. If you use Sync From DB, then new assets will be assigned IDs that are different from the global assets' IDs, so you don't need to worry about unique IDs. However, it's entirely possible that your Desert database could contain IDs that overlap with IDs in your Jungle database. This might be fine, though. As long as you don't load Desert and Jungle at the same time, there won't be any ID conflicts in memory.

    Use one Dialogue Manager, typically added to your main menu scene. You can put other Dialogue Managers in your location scenes so you can test them without having to come in from the main scene. But keep in mind that, in normal gameplay, the Dialogue Manager from the main scene will carry through and destroy the "test" Dialogue Manager in your location scene.

    To load extra databases into memory at runtime, use the Extra Databases component. For example, add an Extra Databases component to an empty GameObject in your Desert scene. Set the Add Trigger to On Start, and assign the Desert database. Set the Remove Trigger to On Destroy, and assign the Desert database.

    If I missed anything or if you have any other follow-up questions, just let me know!
     
    Last edited: Nov 23, 2015
  45. EternalAmbiguity

    EternalAmbiguity

    Joined:
    Dec 27, 2014
    Posts:
    3,144
    I haven't had much time to work on this recently, but given the upcoming break I may get the chance. Thus, I'll ask you about my hopefully final but largest by far (I imagine) request. Quoting myself from my first post here:

    "-player can select a convo option during another character's speech"

    and by extension

    "Also, because of these last two the dialog options will need to appear and vanish based on, I suppose, the time elapsed within the current "segment" or "node" I guess you might say."

    The way I imagine this functioning, in a perfect world, is a type of "timeline" for the dialog. Each response is on the timeline at its own position, and you can enter their "zone" and leave it without activating them. When a response is selected, it moves you to a different timeline where a new set of NPC comments runs, with each response popping up as needed.

    That's in a perfect world. But for reality, do you know how I might go about implementing something similar?
     
  46. maltakereuz

    maltakereuz

    Joined:
    Mar 29, 2015
    Posts:
    53
    Thank you for reasonable explonation. Now i have much less doubts about design of dialog subsystem in game. In my case (just destktop and high and android/ipad) one db for is the easy and straightforward way.

    wow, even better then perfixes
    great feature
     
  47. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,698
    (I might not be understanding your request accurately. If I'm off base, let me know.)

    What about adding a Conversation Trigger to each NPC? You can set the trigger to OnTriggerEnter, and tick Stop Conversation On Trigger Exit. This way the player can join and leave conversations just by walking up to NPCs and then walking away from them.

    If that sounds good so far, then the next step is to resume each conversation where it left off. I suggest making a custom version of Conversation Trigger that records the current dialogue entry ID in a custom field of each character. That way the entry ID gets saved in saved games. You'd do this by adding an OnConversationLine method to be notified of each dialogue entry, and then call DialogueLua.SetActorField to save the entry's ID. When the conversation starts, it can jump back to that entry. If this sounds like the way you want to go, I can post a script here.

    If the NPC will keep talking even if the player doesn't choose a response, then use the Dialogue System's Timeout feature. Set the Dialogue Manager's Input Settings > Timeout value. Make your first player response blank, as if the player chooses not to say anything. If the timer runs out, it will automatically choose this response.

    If I totally missed the point of what you want to do, please give me a concrete example. We'll see if we can put together a prototype to implement that example case.

    Happy to help! :)
     
  48. silentslack

    silentslack

    Joined:
    Apr 5, 2013
    Posts:
    394
    @TonyLi Thanks for all the help and info. I was using 'Mixed' on AssetSerialization and have now put into 'ForceText'. Will see how I get on. Thanks dude.
     
  49. EternalAmbiguity

    EternalAmbiguity

    Joined:
    Dec 27, 2014
    Posts:
    3,144
    This feels like a jumbled mess, but it may aid understanding. Read the bottom part first, and if it isn't clear maybe this will clear it up.
    What you describe at the beginning sounds like a useful solution to something else I'd been worried about-but the problem I'm describing is different. Imagine this:

    A conversation is not a bunch of stop-start sequential steps. It instead flows, and a conversation choice can be introduced (to the player) after a relevant statement by the NPC. However, it does NOT go away when the NPC moves to the next conversation step. It remains possible to choose that response (and it would remain possible to choose that response in the middle of an NPC's statement).

    I'm attempting to replicate the reality of real-life, where one might think of a question to ask someone, but might wait until "the right time" to say it--also having the option to interrupt the other person. Life isn't a dialog tree, it flows like a river.

    I suppose this is possible in the most simplistic sense by keeping those responses available in the subsequent dialog choices (for the later points in a conversation), but that's cumbersome and requires having a new set of choices for each line in the conversation. I don't know if this is totally possible.

    If I'm still not being clear again imagine the timeline. The timeline is pure, 100% NPC. The NPC talks until it runs out of things to say. However, after they say something relevant, you have the option to say something. That option does not appear and disappear based on which step of the conversation you're on, but it is separate and disappears over some individually chosen set of time. Like, it could disappear halfway through a sentence.

    So two main things: player can choose dialog choices while the NPC is talking (so the dialog box never goes away), and the individual dialog choices appear based on the conversation steps, but disappear on an individual timer unrelated to the current "step" of the conversation (so the dialog box never goes away, and each choice appears and disappears independently of the others).

    I imagine a system where each choice has next to it, or perhaps overlaying it, a sort of timer describing how long it will be available (simplistically, a filled bar that moves to zero, individually for each choice). And I want to emphasize that the dialog box would NOT disappear when you select a response and the NPC starts talking, but would remain with all other choices still able to be selected--and able to be selected WHILE the NPC is still talking.
     
  50. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,698
    Hi @EternalAmbiguity - Entirely do-able! Here's how I'd recommend approaching it:

    Dialogue Database
    • Add a Number field named "Timeout" to the dialogue entry template.
    • Write your conversation with only NPC lines. At this point, all the nodes except START should be gray. If you were to play the conversation, the NPC would keep talking from the first node to the last.
    • Add player response (blue) nodes. Set each node's Timeout field to the duration for which it will appear in the menu. Link to them from NPC nodes.
    • When moving from node to node, the Dialogue System will always choose an NPC node if available, so the conversation will flow like you described unless the player interjects a response.

    UI
    • Make a subclass of UnityUIDialogueUI.
    • Declare a dictionary of currently-available responses:
      Code (csharp):
      1. private Dictionary<int,Response> currentResponses = new Dictionary<int,Response>();
      The int key will be for dialogue entry IDs.
    • Override the Open method to also show an empty response menu and clear the dictionary:
      Code (csharp):
      1. public override void Open() {
      2.     base.Open();
      3.     dialogue.responseMenu.SetActive(true);
      4.     dialogue.responseMenu.DestroyInstantiatedButtons();
      5.     currentResponses.Clear();
      6. }
    • Override the ShowResponses and HideResponses methods to do nothing. (Just empty braces.)
    • Override the ShowSubtitle method to also update the response menu. In addition to calling base.ShowSubtitle(subtitle), go through the DialogueManager.CurrentConversationState.pcResponses array. If any of the responses' dialogue entry IDs don't already correspond to a key in the dictionary, add the response as a new button:
      Code (csharp):
      1. public override ShowSubtitle(Subtitle subtitle) {
      2.     base.ShowSubtitle(subtitle);
      3.     foreach (var response in DialogueManager.CurrentConversationState.pcResponses) {
      4.         if (!currentResponses.ContainsKey(response.destinationEntry.id)) {
      5.             AddResponseButton(response); // (see below)
      6.     }
      7. }
      8.  
      9. private void AddResponseButton(Response response) {
      10.     currentResponses.Add(response.dialogueEntry.id, response);
      11.     var button = Instantiate(dialogue.responseMenu.buttonTemplate) as UnityUIResponseButton;
      12.     button.transform.SetParent(dialogue.responseMenu.buttonHolder.transform, false);
      13.     button.response = response;
      14.     button.SetFormattedText(response.formattedText);
      15.     dialogue.responseMenu.NotifyContentChanged();
      16. }
    • In the code above, I omitted the timeout handling. To implement timeouts:
      • Add a method to your UnityUIDialogueUI subclass called something like DeleteExpiredResponses:
        Code (csharp):
        1. private void DeleteExpiredResponses() {
        2.     foreach (var button in dialogue.responseMenu.instantiatedButtons) {
        3.         if (button.GetComponentInChildren<Slider>().value <= 0) {
        4.             currentResponses.Remove(button.response.dialogueEntry.id);
        5.             dialogue.responseMenu.instantiatedButtons.Remove(button);
        6.             Destroy(button);
        7.         }
        8.     }
        9.     dialogue.responseMenu.NotifyContentChanged();
        10. }
      • Add a UI slider child to the button template.
      • Add a UnityUITimer to the slider.
      • In AddResponseButtons, just before calling NotifyContentChanged, get the timeout value and start the timer:
        Code (csharp):
        1. float timeout = Field.LookupFloat(response.dialogueEntry.fields, "Timeout");
        2. var timer = button.GetComponentInChildren<UnityUITimer>();
        3. timer.StartCountdown(timeout, DeleteExpiredResponses);
    • This may take a little tweaking if I've overlooked a step while typing the response in here.
     
    hopeful likes this.