Change database at runtime

Announcements, support questions, and discussion for the Dialogue System.
Post Reply
LostTrainDude
Posts: 69
Joined: Wed Mar 21, 2018 2:14 pm

Change database at runtime

Post by LostTrainDude »

[Unity 2019.4.10f - DS v2.2.10]
Hi Tony!

For testing purposes I'm currently creating a database at runtime from an Articy XML exported file, but I'm not sure how to entirely swap it with the one that was there first in the Dialogue System Controller.

In other words I don't want to add an extra database, I want to entirely switch the previous one with the new imported one. Is this currently possible?

Through code I can swap the defaultDatabase and the initialDatabase into the new one but the masterDatabase, which is - if I'm not wrong - the one that is called by DialogueSystemController.StartConversation(), is read-only and I'm not sure which are the methods to override it (if there are any).

I also tried creating a new DatabaseManager from the one I imported and overwrite the one in the Dialogue System Controller

Code: Select all

dialogueSystemController.databaseManager = new DatabaseManager(importedDatabase);
but databaseManager is also read-only.

I'm trying to read both the code and the documentation but I admit a bit of confusion when it comes to figuring out initialDatabase, defaultDatabase and masterDatabase and what's their respective purpose.

Reading this thread I kind of understand the point
Tony Li wrote: Sat May 20, 2017 2:42 pm At runtime, the Dialogue System maintains a "master database" in memory. When you add a database at runtime, the Dialogue System fills in the master database with any assets (e.g., actors, variables, conversation, etc.) that aren't already in the master database. When you delete a database at runtime, the Dialogue System removes any assets (e.g., conversations) that aren't also defined in other added databases such as the global database.
but, again, I'm not sure how to "overwrite" the previous one with the one I have imported.

It makes me think that I need to .RemoveDatabase()/.AddDatabase() the masterDatabase, so that the system handles the whole process correctly, but I'm not entirely sure how to proceed.

Do you have any suggestions?

Thanks a lot as always, in the meantime!
User avatar
Tony Li
Posts: 21678
Joined: Thu Jul 18, 2013 1:27 pm

Re: Change database at runtime

Post by Tony Li »

Hi,

At design time, just assign your database (the one created by the articy importer) to the Dialogue Manager's Initial Database field.

If you're creating the database from XML at runtime, you'll need to use AddDatabase.

The DialogueManager.masterDatabase property is just a representation of all databases that happen to be loaded at the time.
LostTrainDude
Posts: 69
Joined: Wed Mar 21, 2018 2:14 pm

Re: Change database at runtime

Post by LostTrainDude »

Hi Tony, thanks for the answer!

What I'm experiencing with AddDatabase() is that the one I import at runtime - in fact - gets "appended" to the one that's already there. Am I correct?

What I was looking for was a way to "ditch" the previously loaded one, and only keep the new one I imported at runtime.

As an example, picture me running the scene with some dialogue in it.
I want to amend something in the dialogue itself, so I go back to Articy and edit the dialogue, then reexport the XML file.

Back in my scene I have set up a button that whenever I press it I want it to reimport the Database entirely, thus deleting the one that was there before and only keep the new one, without having to reboot the scene again.
User avatar
Tony Li
Posts: 21678
Joined: Thu Jul 18, 2013 1:27 pm

Re: Change database at runtime

Post by Tony Li »

If you want to do this while the game is playing, use RemoveDatabase first, then AddDatabase.

If you want to save retain any variable changes made during play, use PersistentDataManager.GetSaveData to save the variable values to a string first. After replacing the database, use ApplyData to restore the variable values.

If you're doing this outside of play mode, you can configure the importer to overwrite.
LostTrainDude
Posts: 69
Joined: Wed Mar 21, 2018 2:14 pm

Re: Change database at runtime

Post by LostTrainDude »

Hi Tony, thanks again for the answer.

I'm getting somewhere, but what's happening now is that the conversation skips every player choice.

This is my script:

Code: Select all

public class DialogueTester : MonoBehaviour
{
    DialogueSystemController dsc;
    DialogueDatabase originalDatabase;

    void Start()
    {
        dsc = GetComponent<DialogueSystemController>();
		
	// cache the original database
        DatabaseManager tempManager = new DatabaseManager(dsc.initialDatabase);
	originalDatabase = tempManager.defaultDatabase;
    }

    public void OnGUI()
    {
        using (new GUILayout.HorizontalScope(GUI.skin.GetStyle("Box")))
        {
            using (new GUILayout.HorizontalScope())
            {
                if (GUILayout.Button("Load new database"))
                {
                    dsc.RemoveDatabase(dsc.databaseManager.defaultDatabase); // ?
                    dsc.AddDatabase(ImportDatabaseFromXML());
                }

                if (GUILayout.Button("Reset Database to default"))
                {
                    dsc.RemoveDatabase(dsc.databaseManager.defaultDatabase); // ?
                    dsc.AddDatabase(originalDatabase);
                }
            }
        }

        ShowConversationsOnGUI();
    }

    private void ShowConversationsOnGUI()
    {
        using (new GUILayout.HorizontalScope(GUI.skin.GetStyle("Box")))
        {
            using (new GUILayout.VerticalScope())
            {
                foreach (Conversation conversation in dsc.masterDatabase.conversations) // ?
                {
                    using (new GUILayout.HorizontalScope())
                    {
                        GUILayout.Label(conversation.Title);

                        if (GUILayout.Button("Play", GUILayout.Width(64f)))
                        {
                            dsc.StartConversation(conversation.Title);
                        }
                    }
                }
            }
        }
    }

    private DialogueDatabase ImportDatabaseFromXML()
    {
        var xmlData = System.IO.File.ReadAllText(Application.streamingAssetsPath + "/test.xml");
        return PixelCrushers.DialogueSystem.Articy.ArticyConverter.ConvertXmlDataToDatabase(xmlData);
    }
}
I have commented with question marks the lines that I think I'm getting wrong even though, removing dsc.databaseManager.defaultDatabase and iterating through dsc.masterDatabase.conversations is the only combination to apparently update the GUI so that it lists the conversations inside the "current database" I want to use.
User avatar
Tony Li
Posts: 21678
Joined: Thu Jul 18, 2013 1:27 pm

Re: Change database at runtime

Post by Tony Li »

Hi,

Try this. It's a bit more compact:

Code: Select all

public class DialogueTester : MonoBehaviour
{

    public void OnGUI()
    {
        using (new GUILayout.HorizontalScope(GUI.skin.GetStyle("Box")))
        {
            using (new GUILayout.HorizontalScope())
            {
                if (GUILayout.Button("Load new database"))
                {
                        DialogueManager.databaseManager.Clear();
                        DialogueManager.AddDatabase(ImportDatabaseFromXML());
                }

                if (GUILayout.Button("Reset Database to default"))
                {
                        DialogueManager.databaseManager.Clear();
                        DialogueManager.AddDatabase(DialogueManager.instance.initialDatabase);
                }
            }
        }

        ShowConversationsOnGUI();
    }

    private void ShowConversationsOnGUI()
    {
        using (new GUILayout.HorizontalScope(GUI.skin.GetStyle("Box")))
        {
            using (new GUILayout.VerticalScope())
            {
                foreach (Conversation conversation in DialogueManager.masterDatabase.conversations)
                {
                    using (new GUILayout.HorizontalScope())
                    {
                        GUILayout.Label(conversation.Title);

                        if (GUILayout.Button("Play", GUILayout.Width(64f)))
                        {
                            DialogueManager.StartConversation(conversation.Title);
                        }
                    }
                }
            }
        }
    }

    private DialogueDatabase ImportDatabaseFromXML()
    {
        var xmlData = System.IO.File.ReadAllText(Application.streamingAssetsPath + "/test.xml");
        return PixelCrushers.DialogueSystem.Articy.ArticyConverter.ConvertXmlDataToDatabase(xmlData);
    }
}
Also, I don't think this will make a difference, but the Extras page has an articy import patch that fixes the actor assignments of certain types of "decorator" nodes such as jumps and pins.
LostTrainDude
Posts: 69
Joined: Wed Mar 21, 2018 2:14 pm

Re: Change database at runtime

Post by LostTrainDude »

Hi Tony,
thanks for the more compact code.

.Clear() seems quite handy and didn't really spot it before. It helps making things less confusing for me.

This, and a few more hours of testing made me find out that part of the problem was that the Articy entities didn't 100% conform to what the Converter was expecting (e.g. not all NPCs having the IsNPC flag, etc.).

This now seems to be working as intended!

Thanks a lot again!
User avatar
Tony Li
Posts: 21678
Joined: Thu Jul 18, 2013 1:27 pm

Re: Change database at runtime

Post by Tony Li »

Glad to help!
Post Reply