Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

[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,670
    There's a typo in the Quest Log System documentation for NGUI quest log windows. I'll fix it today.

    Where it says:
    it should say:
     
  2. barjed

    barjed

    Joined:
    May 9, 2013
    Posts:
    70
    Thanks for all your answers Tony!

    One last question. This one comes from my curiosity:

    I understand that this won't be an issue with 1.1.8 but how exactly did it work in the past if a conversation had more than one conversant (player + 2 npcs), if the name is of the conversant is directly tied to the name of the prefab that triggered the conversation?
     
  3. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    For extra actors (e.g., the second NPC), it grabs the name from the database. If it can find a GameObject matching that name, it will temporarily set the speaker transform to that GameObject while the line is being delivered.
     
  4. Deleted User

    Deleted User

    Guest

    Thanks for a great update, it's really really nice!

    I saw you wrote that the HUD is responsible for showing the tracked info, which is good. It should be quite easy to do with a Label in Daikon Forge. I was however wondering if you have any pointers as to how to retrieve the quests that are currently on "track", so I can create a script on the Track_Label gameobject that puts the trackable text (for example the quest name and quest text) in it?
     
  5. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    Hi speedis, you can get a list of all quests using QuestLog.GetAllQuests() and then check QuestLog.IsQuestTrackingEnabled() for each one. Something like:
    Code (csharp):
    1.  
    2. foreach (string quest in QuestLog.GetAllQuests()) {
    3.     if (QuestLog.IsQuestTrackingEnabled(quest)) {
    4.         Debug.Log(string.Format("Tracking quest {0} with description {1}", quest, QuestLog.GetQuestDescription(quest)));
    5.     }
    6. }
    7.  
    You can also add a script to the Dialogue Manager object that listens for OnQuestTrackingEnabled() and OnQuestTrackingDisabled(). These get broadcast to the Dialogue Manager object and its children whenever the player toggles tracking in a quest log window.

    If you have any other ideas to make it easier to handle quest tracking, please let me know!
     
  6. Deleted User

    Deleted User

    Guest

    Thanks a lot, Toni!

    I created a QuestTracker script that I attached to the Dialogue Manager, but get the following error;
    Code (csharp):
    1. QuestTracker.cs(22,51): error CS0121: The call is ambiguous between the following methods or properties: `PixelCrushers.DialogueSystem.QuestLog.GetAllQuests()' and `PixelCrushers.DialogueSystem.QuestLog.GetAllQuests(PixelCrushers.DialogueSystem.QuestState)'
    Not sure if its a bug or not.


    This is the code;
    Code (csharp):
    1. using UnityEngine;
    2. using System;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5. using PixelCrushers.DialogueSystem;
    6.  
    7. public class QuestTrackerListener : MonoBehaviour
    8. {
    9.     public dfLabel questTrackerLabel;
    10.  
    11.     public void OnQuestTrackingEnabled(string questTitle)
    12.     {
    13.         UpdateTracker();
    14.     }
    15.  
    16.     public void OnQuestTrackingDisabled(string questTitle)
    17.     {
    18.         UpdateTracker();
    19.     }
    20.  
    21.     void UpdateTracker()
    22.     {
    23.         foreach (string quest in QuestLog.GetAllQuests())
    24.         {
    25.             if (QuestLog.IsQuestTrackingEnabled (quest))
    26.             {
    27.                 Debug.Log (string.Format ("{0} \n {1} \n \n", quest, QuestLog.GetQuestDescription (quest)));
    28.             }
    29.         }
    30.     }
    31. }
     
  7. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    Sorry, try QuestLog.GetAllQuests(QuestState.Active);
     
  8. Deleted User

    Deleted User

    Guest

    Thanks, it's working perfectly now! :)
     
  9. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    Great to hear!

    I'm expanding the included demo scene in the next release to demonstrate text input (for the computer terminal), quest entries, quest tracking, and the ability to abandon quests.

    [HR][/HR]

    Version 1.1.8 is now available on the Asset Store! If you prefer to update through the Asset Store rather than the customer download page, you can do it now.
     
  10. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    The latest version of plyGame introduced some changes that required an update to the Dialogue System's plyGame Support package. Customers can download it from the customer download page. If you need access, please PM me your invoice number.
     
  11. DieHappyGames

    DieHappyGames

    Joined:
    Feb 24, 2014
    Posts:
    44
    Just wondering if/when there will be more tutorial videos available - found them extremely helpful :)
     
  12. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    The next two on the list are quests and Lua, but I'm taking suggestions. If there's demand for a different tutorial first, please let me know! :)
     
  13. DieHappyGames

    DieHappyGames

    Joined:
    Feb 24, 2014
    Posts:
    44
    Quests and Lua were exactly what I was hoping for :) I'm guessing further understanding of Lua is what's going to allow for expanded functionality between DS and the rest of Unity, such as a line of dialogue that modifies a variable in the script of another game object, or being able to include methods in a C# script that will check/modify items, variables, etc. in a Dialogue Database.
     
  14. DieHappyGames

    DieHappyGames

    Joined:
    Feb 24, 2014
    Posts:
    44
    With regards to the "Once" flag on conversations, I was wondering if there's a Lua function (or some other means) for checking whether that "one time" has/hasn't occurred? Practical application, I'm thinking of an NPC who would have a conversation when first spoken with, but then bark lines after that conversation has taken place. I realize I could do this with a Lua variable or item state, but thought I'd check in case there's already something built-in for checking whether a Once has been fulfilled.

    On somewhat related note, how do Chatmapper's line priorities work within DS? I don't see anywhere within the editor for setting a line's priority - am I wrong? If not, will DS still handle them in the same way that Chatmapper does when simulating a conversation?
     
  15. DieHappyGames

    DieHappyGames

    Joined:
    Feb 24, 2014
    Posts:
    44
    One last thing for today (sorry for spamming the thread). Two things that I'd love to know how to do if possible and would make great built-in features if it's not too much work for you:
    - Being able to override actor portrait on a line-by-line basis within the editor (to convey emotion jrpg-style)
    - Being able to set an animation clip (or animator controller?) for the actor portrait, as a way of simulating lip sync, idles, etc.
     
  16. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    The "Once" flag works by destroying the trigger component. So it'll be best to use a Lua variable. Or you could use the SetEnabled() sequencer command in the conversation to enable the bark trigger. That way you don't need any conditions. The bark trigger just stays inactive until it's ready to be used.

    Priorities work exactly the same in Chat Mapper and the Dialogue System. In the Dialogue Editor, you can set the priority next to each link in the dialogue entry section. The dropdown defaults to Normal.

    To override the portrait, use the SetPortrait() sequencer command. The texture needs to be under a Resources folder since it's loaded at runtime.

    Portraits are plain Texture2D's. There's no built-in way to animate them. But you could always add your own elements and use sequencer commands to control them.
     
  17. halfbot

    halfbot

    Joined:
    Sep 22, 2013
    Posts:
    19
    Tony,
    Quick question. Not sure if you have addressed this already or this is easy to do.
    I need to know when a sequence is completed between conversations. My sequence : Camera(Full, HeroCamera, 2); Delay(2); needs to be done in order for continue button to show. Right now continue show up before the sequence is done. As long as I can flag the sequence done somehow I would be able to achieve what I want.

    Any way of doing this?

    Thanks

    Edit:

    Would you suggest using a custom Sequence Command to do this?
     
    Last edited: Mar 6, 2014
  18. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    Hi halfbot, you're right -- the default behavior shows the continue button immediately in case the player wants to click it to skip ahead before the sequence is done. If you give your continue buttons unique names (e.g., "NPC Continue Button" and "PC Continue Button"), you can hide and show them in sequences using the existing SetActive() sequencer command:
    Code (csharp):
    1.  
    2. // SetActive(NPC Continue Button,false); Camera(Full, HeroCamera, 2); SetActive(NPC Continue Button,true)@2
    3.  
    That'll work fine if you only need to do it every once in a while. But if you're doing this for a lot of sequences, it's too much work. If most of your dialogue entries use the default sequence defined on the Dialogue Manager object, then it's not so much work.

    You can also hide the continue button automatically by using a subclass of your dialogue UI class (e.g., a subclass for UnityDialogueUI). Override ShowSubtitle() to hide the button:
    Code (csharp):
    1.  
    2. public override void ShowSubtitle(Subtitle subtitle) {
    3.     base.ShowSubtitle(subtitle);
    4.     HideContinueButton(subtitle); // <-- Add this line.
    5. }
    6.  
    Probably the best method:
    Conversations (used to) purposely suppress the "OnSequenceStart" and "OnSequenceEnd" messages for dialogue entries to reduce the number of messages being broadcast. However, I just posted a hotfix patch on the customer download page. (I'll PM you the access info.) It adds a checkbox where you can re-enable this behavior.

    With this patch, you can add a script to your player object that listens for OnSequenceStart() and OnSequenceEnd() to hide and show the button. Something like:
    Code (csharp):
    1.  
    2. public class ManageContinueButton : MonoBehaviour {
    3.  
    4.     public GameObject continueButton; // <-- Assign this.
    5.  
    6.     void OnSequenceStart(Transform actor) {
    7.         continueButton.SetActive(false);
    8.     }
    9.  
    10.     void OnSequenceEnd(Transform actor) {
    11.         continueButton.SetActive(true);
    12.     }
    13. }
    14.  
    Then you don't need to fiddle with anything inside the sequences themselves.

    [HR][/HR]

    Patch 1.1.8.1a:
    • New: Dialogue Manager > Subtitle Settings > Inform Sequence Start And End checkbox to enable OnSequenceStart()/OnSequenceEnd() messages on dialogue entries.
    • Fixed: DialogueLua.SetVariable() and SetItemTable() were incorrectly setting Boolean values as strings.
    • Updated: plyGame support.
     
  19. DieHappyGames

    DieHappyGames

    Joined:
    Feb 24, 2014
    Posts:
    44
    Having trouble getting this to work as intended. I put the texture that I know works for portraits into the Resources folder and call the sequencer SetPortrait(NPC, newPortrait) but instead of it swapping the portrait for that one line, it breaks the conversation (ends without displaying that line) and then permanently changes the portrait of that actor, such that if I then hit play again, what was intended to be NPC's temporary portrait is now his constant one. Am I missing something...?
     
  20. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    SetPortrait() changes the texture permanently until you change it back. This way, if you make an NPC angry, you don't have to keep setting the angry portrait for every single line. Visually, it takes effect the next time the portrait image is updated in the UI -- that is, the next line spoken by that NPC. It's useful to set it in the PC's line. So if the PC says "You're momma's so fat....", you can set the NPC to an angry portrait in that line.

    Does anyone think it would be better to take immediate visual effect? (Let me know!)

    Would you please set the Dialogue Manager's Debug Level to Info and email me the editor log? I'm not able to reproduce the conversation break you described.
     
  21. DieHappyGames

    DieHappyGames

    Joined:
    Feb 24, 2014
    Posts:
    44
    Ah, that's what I was missing - that the sequence that changes the character's portrait needs to be on the line that precedes the one where you want it shown. As for why it was killing the conversation, it appears to have been because I had the sequence on the last line of the conversation, which was the one where I wanted the expression change seen - I'm guessing that when it attempted to run a sequence that was meant to affect a non-existing "next line" it skipped forward, ending the conversation(?) Once I switched the sequence to the preceding line, it played out properly. The only thing that concerns me is I could see a number of practical applications where you would want to switch the profile back at the end of the conversation (in preparation for the next time that character speaks) but that wouldn't work if putting the sequence on the last line causes that line to skip...
     
  22. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    What is the duration of the last line's sequence? If it's zero, the line will appear to skip. The commands will run but finish immediately, so the player won't see anything.
     
  23. halfbot

    halfbot

    Joined:
    Sep 22, 2013
    Posts:
    19
    Thanks Tony. That was a very thorough answer. I appreciate the quick reply and patch update.
     
  24. Pauloxande

    Pauloxande

    Joined:
    Feb 8, 2014
    Posts:
    110
    friend how do I edit the conversations editor, the button to put new entries have not?
    Or do I have to use the ChatMapper

    See: $Sem título.jpg
     
  25. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    Hi Pauloxande, please update to the latest version of the Dialogue System, or at least version 1.1.6. It provides a new Dialogue Editor window. On the tutorials page, you can view a tutorial on the Dialogue Editor window. The latest version on the Asset Store is 1.1.8. If you would like access to 1.1.8.1a, please PM me your invoice number.

    I'm not sure I understand your question. If you want to remove the (New Entry) option from the "Link To:" pop-up menu, you will have to modify the source code. To do this, you have to unpack the source code. (Please read the notes in that link.)

    Then comment out line 457 of Scripts/Core/Editor/Dialogue Editor/DialogueEditorWindowDialogueTreeSection.cs:
    Code (csharp):
    1.  
    2. // destinationList.Add("(New Entry)");
    3.  
     
  26. DieHappyGames

    DieHappyGames

    Joined:
    Feb 24, 2014
    Posts:
    44
    How do I set the duration of the line's sequence? Do you mean delaying it a few seconds by adding @3 to the SetPortrait sequence? I would have thought adding "Delay({{end}})" either before or after the SetPortrait sequence would allow the line to play out at its normal pace, but neither worked...
     
  27. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    Try "Delay(2)" or some other number. The {{end}} keyword is currently only defined for the Dialogue Manager's Default Sequence. While testing my earlier reply about SetPortrait(), I left a post-it on my desk to support {{end}} in all dialogue entry sequences, and it's now in the official "to do" database for the next release.
     
  28. DieHappyGames

    DieHappyGames

    Joined:
    Feb 24, 2014
    Posts:
    44
    Thanks Tony, I'll wait for the next update before messing around with dynamic portraits much more. I do still think that the way it goes about overriding portraits (directly changing the actor setting in the dialogue database) may warrant some refinement. I can see the appeal in its current design, so that you can switch back and forth rather than having to override four lines in a row, but the way it works now because it's modifying the original asset, I've had it lead to weird scenarios, such as if the Player escapes out of a conversation in the middle of "angry face" then restarts the game, that npc will have "angry face" right from the beginning.

    My workaround for this will be to create a sequence onStart and/or OnDialogue(/End) that resets all actor portraits to their default ones. Just something to consider...
     
  29. branden

    branden

    Joined:
    Aug 8, 2012
    Posts:
    3
    When I set up this scene from scratch using Unity's Construction Worker, he keeps rotating in the x-axis strangely when I talk to him. I think it may be in attempt to face the player. Is there a way to constrain this behavior in the x-axis? Or any tips on how to do this and make it not look so ridiculous lol!

    Loving your asset so far :D!

    $beforetalk.jpg



    $aftertalk.jpg
     
  30. DieHappyGames

    DieHappyGames

    Joined:
    Feb 24, 2014
    Posts:
    44
    That's a product of the "Default Sequence" under "Camera Settings" in the Dialogue Manager you have placed in your hierarchy. You can change it to "Delay({{end}})" to remove the effects entirely or build your own custom sequence, such as one that includes facing the player on only one axis. Watch the videos on Cutscene Sequences and Camera Angles available at the link below - they are very helpful.

    http://www.pixelcrushers.com/dialogue-system-tutorials/
     
  31. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    Thanks, Dave! That gets a lot of people. Maybe I should change the default to leave the camera untouched.

    [hr][/hr]

    Version 1.1.9 has been released! It's available for immediate download on the customer download site, and should be available on the Asset Store in 5-7 days. If you need access to the customer site, please PM me your invoice number.

    Highlights include:
    • Unique ID tool for multiple databases: Makes sure dialogue databases have unique IDs to avoid conflicts when loading unloading multiple databases.
    • SetPortrait() improved: Now sets an override in the Lua environment instead of modifying the database.
    • {{end}} tag: You can now use the {{end}} tag in any dialogue entry sequence, not just the default sequence.
    • Quest tracker HUD: Basic in-game quest tracking HUD, usable in conjunction with toggling Track in the quest log window.

    The full list of changes is:

    Version 1.1.9:
    • New: Unique ID Tool to guarantee unique IDs across dialogue databases.
    • New: Quest Tracker HUD component.
    • Improved: Added demonstrations of text input and quest tracking to the feature demo scene.
    • Improved: The {{end}} tag is now supported in any dialogue entry sequence.
    • Improved: Sequence subjects can use "/" to access child objects (e.g., Animation(Character/Model, Idle)). Note:
    • SetActive(parent/child) doesn't find inactive children.
    • Improved: Added Dialogue Manager Display Setting "Inform Sequence Start And End".
    • Improved: DialogueLua.IncRelationship()/DecRelationship() on an undefined relationship value initializes the value to zero first.
    • Changed: SetPortrait() now sets a Lua field rather than modifying the dialogue database.
    • Fixed: DialogueLua.SetVariable()/SetItemField() handled non-string values incorrectly.
    • Fixed: Bug in display of Dialogue Editor drop-down fields when there were gaps in IDs.
    • Fixed: Unity GUI NGUI barks were showing even if camera was facing 180 degrees away.
    • (plyGame) Updated plyGame support package to handle changes to plyGame.
    • (2D Toolkit) Implemented ITextFieldUI.

    Next on the roadmap are:
    • XML export to Chat Mapper
    • More video tutorials: Quests, Using Lua, and Working with Multiple Databases
     
  32. branden

    branden

    Joined:
    Aug 8, 2012
    Posts:
    3
    Thanks for the quick reply! I figured it was something simple XD!
     
  33. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    Hi barjed, version 1.1.9 now supports this. The only thing you can't do is activate inactive children using SetActive(parent/child, true). I'm not aware of a reliable way to find inactive children. If the child has a unique name, you can activate it directly -- e.g., SetActive(uniqueChildName, true).
     
  34. DieHappyGames

    DieHappyGames

    Joined:
    Feb 24, 2014
    Posts:
    44
    Hey Tony, unless there's a setup step I'm missing, the vertical axis navigation of dialogue menus doesn't seem to work. I followed your earlier steps to get it working with the up/down arrows, but the panel seems to suggest you can additionally set navigation by horizonal/vertical axis, which would encompass either gamepad or wasd on the keyboard, but it doesn't seem to actually work(?)
     
  35. barjed

    barjed

    Joined:
    May 9, 2013
    Posts:
    70
    Wow, I'm amazed at your speed. Fantastic, thanks!

    Tony,

    Is it possible to have the typewriter effect finish up instantly when the "Continue" button is pressed, instead of skipping straight to the next dialogue? This is default behavior of all modern games with large amounts of text.

    Thanks!
     
    Last edited: Mar 10, 2014
  36. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    Hi Dave, I'll look into this and get back to you. I tested it with an Xbox 360 controller connected to a Windows 7 box. What input device are you using? Since Axis Repeat Delay is set to 1, it should move between each item after holding down for 1 second, or by pressing and releasing (like gamepad navigation usually works). If your mouse cursor is hovering over a button, it takes precedence, so it will always focus that button.

    Hi barjed, I'll put out a patch in a few days to give you this option. The default behavior will remain the same, since many people use the continue button to mean "skip ahead." But you'll be able to override it to do what you described.
     
  37. DieHappyGames

    DieHappyGames

    Joined:
    Feb 24, 2014
    Posts:
    44
    For me, it's not working with either the gamepad axis or the keyboard axis(wasd). The inputs themselves are definitely working, as they're what currently control my player's movement. the gamepad I'm using is a wireless 360 controller, though I've also tried to no avail with it directly connected via USB. Dialogue Manager Debug Level set to Info reports nothing when either the keys are pressed or the analogue is pushed (and mouse is nowhere near the dialogue box). Do I need to (/ can I anyway) disable the mouse cursor during gameplay?
     
  38. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    It's fixed now. Sorry, I had disabled it when testing mouse scroll wheel navigation. I'll put a patch on the download page and post here when it's ready. The Unity dialogue UI just uses Unity GUI's default mouse behavior. You can disable the mouse with Screen.lockCursor = true. For example, you could add these methods to a script on the Dialogue Manager or Player:
    Code (csharp):
    1.  
    2.     public void OnConversationStart(Transform actor) {
    3.         Screen.lockCursor = true;
    4.     }
    5.  
    6.     public void OnConversationEnd(Transform actor) {
    7.         Screen.lockCursor = false;
    8.     }
    9.  
     
  39. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    Dave, patch 1.1.9a is on the customer download site now. Gamepad navigation works again. :)

    barjed, I had to put together a patch anyway, so this is included. To use it:
    1. Add this component to your Continue Button: Window > Dialogue System > Component > UI > Unity GUI > Controls > Effect > Continue Button Fast Forward.
    2. Assign the dialogue UI and the label with the typewriter effect.
    3. Change the button's message to OnFastForward and the target to the button itself.
    It should look something like this:
    $dialogueUI_continueFastForward.jpg

    It works with the Unity Dialogue UI. In the future, I'll introduce something similar for the other GUI systems. Here's the code (without comments for brevity) in case you want to write your own version for a different GUI system:

    Code (csharp):
    1.  
    2.     public class ContinueButtonFastForward : MonoBehaviour {
    3.  
    4.         public UnityDialogueUI dialogueUI;
    5.         public TypewriterEffect typewriterEffect;
    6.  
    7.         public void OnFastForward() {
    8.             if ((typewriterEffect != null)  typewriterEffect.IsPlaying) {
    9.                 typewriterEffect.Stop();
    10.             } else {
    11.                 if (dialogueUI != null) dialogueUI.OnContinue();
    12.             }
    13.         }
    14.        
    15.     }
    16.  
    When the continue button is clicked: If the typewriter effect is still playing, it stops it and displays all the text immediately. If the typewriter effect is already done, it continues to the next stage.
     
  40. DieHappyGames

    DieHappyGames

    Joined:
    Feb 24, 2014
    Posts:
    44
    That's perfect - I was looking for that sort of functionality as well, thanks!
     
  41. TopThreat

    TopThreat

    Joined:
    Aug 7, 2012
    Posts:
    136
    Hi TonyLi,

    Maybe you can save me some time with some of your magic :)

    Saving the Game:

    1) When changing scenes I would like it to save location and game state, how do I do this?
    2) When returning from my mini-game scene I would like it to load back into the game scene at the location that was previously saved. How?
    3) At the start menu I would like a Load Game button to exist that takes the player back to the last save point in the game. This could be in any of my 16 scenes... How do I do that?

    Hopefully these are challenges you have already faced and don't mind sharing some solutions for :)

    Thanks!!

    Lee
     
  42. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    Hi Lee, add a Persistent Position Data component to each actor (Window > Dialogue System > Component > Save System > Persistent Position Data). Before changing scenes, call PersistentDataManager.Record(). Example:
    Code (csharp):
    1.  
    2. void GotoLevel(string levelName) {
    3.     PersistentDataManager.Record();
    4.     Application.LoadLevel(levelName);
    5. }
    6.  
    This records (into the Lua environment) the current position and rotation for every object that has a Persistent Position Data component. The Lua environment survives scene changes because it's in a static class independent of scenes.

    After loading the scene (for example, in OnLevelWasLoaded()), call:
    Code (csharp):
    1.  
    2. void OnLevelWasLoaded(int level) {
    3.     PersistentDataManager.Apply();
    4. }
    5.  
    This tells every object that has a Persistent Position Data component to retrieve its info from Lua and apply it.

    This part's a little more complicated because every game is different. That's why Unity doesn't have a built-in save system.

    You can write your own persistent data component. There's a template in Scripts/Templates. You just need to implement two methods (OnRecordPersistentData and OnApplyPersistentData). At your save point, you'll probably want to save the name of the level into a Lua variable, something like:
    Code (csharp):
    1.  
    2. public void OnRecordPersistentData() {
    3.     DialogueLua.SetVariable("SavedLevelName", myLevelName);
    4. }
    5.  
    You can leave OnApplyPersistentData() empty.

    When you get to a save point, you'll want to actually save the Lua environment to somewhere that lasts between play sessions. Here's an example:
    Code (csharp):
    1.  
    2. void RecordSavePoint() {
    3.     PlayerPrefs.SetString("SavedGameState", PersistentDataManager.GetSaveData());
    4. }
    5.  
    GetSaveData() first runs Record(), then returns a string containing the game state. Here's a complete list of what gets saved. BTW, there are equivalent PlayMaker and plyGame actions for all of these if you want to avoid code. My example used PlayerPrefs, but you could save the string wherever you want.

    When you load the start menu, recover the Lua environment so you can get the value of Variable["SavedLevelName"]:
    Code (csharp):
    1.  
    2. PersistentDataManager.ApplySaveData(PlayerPrefs.GetString("SavedGameState"));
    3.  
    When the player is ready to resume playing, load the level:
    Code (csharp):
    1.  
    2. Application.LoadLevel(DialogueLua.GetVariable("SavedLevelName");
    3.  
    You can read more in the Save/Load System documentation. It's designed to reliably save the Dialogue System environment, and works well for other uses as long as you don't mind writing your own persistent data components to tell it what to save into the Lua environment. If you have complicated save/load requirements, you might consider a dedicated product such as Easy Save 2. Integrating the Dialogue System's Save/Load System into Easy Save 2 takes just two lines of code as described in this FAQ.

    BTW, there's also a built-in Persistent Active Data component if you want the game state to keep track of objects that have been activated or deactivated. It works a little differently, so read the short documentation if you want to use it.

    In the Feature Demo, the actors use Persistent Position Data components. The computer terminal objects use Persistent Active Data. There are actually two terminals -- one "powered off", and one powered on and ready to log in. Depending on the state of the quest, one gets activated and the other deactivated when a game is loaded. But to the player they look like the same terminal, sometimes powered on, sometimes off.
     
    Last edited: Mar 12, 2014
  43. TopThreat

    TopThreat

    Joined:
    Aug 7, 2012
    Posts:
    136
    Thank you TonyLi, I will try out the examples you provided and potentially buy the Easy Save since it links into your system so easily.
     
  44. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    To better support third-party products that require Unity 4.3.3, I plan to release the next version of the Dialogue System for Unity for 4.3.3+. If any current customers have a strong need to remain on a lower version, please let me know within the next 7 days. Thanks!
     
  45. Antigono

    Antigono

    Joined:
    Oct 20, 2013
    Posts:
    63
    HI! this must have been already answered but I can not find it.
    Is there any way to run an animation (for example a talk animation) when a NPC is talking or while the NPC talk subtitle is showing up?
    I am using Mecamin.

    If this is possible and documented would be useful to indicate me where.

    Thank you very much and im sorry for my English!
     
  46. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    Hi Antigono, yes, this is a fundamental feature. Every dialogue entry has a cutscene sequence. In the dialogue entry's Sequence field, you can use sequencer commands to run animations, play audio, move the camera, and much more. If the built-in commands aren't sufficient, you can also write your own commands using a simple template in Scripts/Templates. If you want to use an interactive, scrubbing sequencer instead, there's built-in support for uSequencer, as well as built-in support for FaceFX. (You have to own a copy of FaceFX to use it, though.)

    On the tutorials page, there's a video tutorial on cutscene sequences.

    On the demos page, the Zombie Demo demonstrates lip-sync'ed audio and animation. It uses non-redistributable art assets, so the project isn't downloadable, but it only uses the built-in features of the Dialogue System and took just a few minutes to put together (plus time to generate the lip sync animation in FaceFX).

    If I can provide any more info or help, please let me know!
     
    Last edited: Mar 13, 2014
  47. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    Hotfix patch 1.1.9c is available on the customer download page. Please PM me your invoice number if you need access. It's meant to be imported on top of 1.1.9 - 1.1.9b and includes:
    • New: Continue Button Fast Forward (two-stage typewriter effect skipahead) for Unity GUI.
    • Fixed: Gamepad navigation of Unity Dialogue UIs.
    • Fixed: Dialogue Manager loads conversations with incorrect IDs more robustly.
    • Fixed: Custom sequencer cameras weren’t destroying themselves properly.
     
  48. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    Sorry, this might not be clear. You don't have to apply 1.1.9a or 1.1.9b. As long as you're running 1.1.9, 1.1.9a, or 1.1.9b, you can install 1.1.9c on top of it.
     
  49. DieHappyGames

    DieHappyGames

    Joined:
    Feb 24, 2014
    Posts:
    44
    Hi Tony,

    I've tried to follow what's in the documentation and your comments to LeeAllen but I'm having trouble getting the saving system to work. I don't really care about saving to a file (will likely use Easy Save for that eventually) but I'm just trying to get the Dialogue Manager to remember the state of my items/variable/conversations/etc when the player moves from one level to another. For example, I have an NPC in Level1 with a conversation that's marked as once. I'm trying to make so that if the Player has that conversation and leaves Level1, the Dialogue Manager should remember that the conversation has taken place, such that if the Player then returns to Level1 and tries to talk to the NPC, it won't work, since he's already done so.

    My Dialogue Manager is set to Don't Destroy on Load and Allow Only One Instance, in case that has any bearing. Greatly appreciate your help,
    Dave
     
  50. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    Hi Dave, Don't Destroy On Load and Allow Only One Instance is the way to go, especially if you're switching scenes or using multiple databases.

    The "Once" checkbox is an exception to the save/load system. It's inspired by NGUI's "Once" checkbox on GUI effects and works the same way: when it's done, it destroys itself. Since it's a checkbox on the component, and not something in a dialogue database, it's not saved in the Lua environment (which is where the save/load system gets its data).

    Here are some options for handling the "Once" checkbox:
    • Use a Lua or Quest condition on your conversation trigger (maybe set a Variable["TalkedToNPC"] to true in the conversation).
    • Put the conversation trigger on a child object and use a Persistent Active Data component to activate or deactivate it based on a condition (e.g., Variable["TalkedToNPC"]==true).
    • Write your own persistent data component that implements OnApplyPersistentData(). If Variable["TalkedToNPC"]==true, destroy the trigger.
    • Always start the conversation, but put a condition in the START dialogue entry that branches to a short subtree, something like: "I already talked with you. Bye."