[Solved] Create linked nodes with code

Announcements, support questions, and discussion for the Dialogue System.
Post Reply
ichisan
Posts: 10
Joined: Thu Dec 07, 2017 12:38 am
Location: Indonesia

[Solved] Create linked nodes with code

Post by ichisan »

Hi Tony. Sorry, I need your help again,
I have massive text to input (5k lines in spreadsheet). So I think it's easier for me to export the spreadsheet, put the text, and then import it.
So, to do that, I need to automatically create numbers of nodes, which is I tried, but the outcome is not what I want it. Here's the code:

Code: Select all

[ExecuteInEditMode]
public class AddchildDialogueManager : MonoBehaviour
{
    public bool execute = false;
    public DialogueDatabase db;
    public int idConversation = 0;
    public int numberCreate = 0;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        if (execute)
        {
            List <DialogueEntry> entries = db.conversations[idConversation].dialogueEntries;
            for(int i=0; i < numberCreate; i++)
            {
                DialogueEntry prevEntry = entries[entries.Count - 1];
                DialogueEntry entry = new DialogueEntry();
                entry.id = entries[entries.Count - 1].id + 1;
                prevEntry.outgoingLinks.Add(new Link(idConversation, prevEntry.id, idConversation, entry.id));
                entries.Add(entry);
            }
            db.conversations[idConversation].dialogueEntries = entries;
            execute = false;
        }
    }
}
And the output become like this :
Image

And it gaves me this null refference errors:
NullReferenceException: Object reference not set to an instance of an object
PixelCrushers.DialogueSystem.Field.SetValue (System.Collections.Generic.List`1 fields, System.String title, System.String value, FieldType type) (at Assets/Plugins/Pixel Crushers/Dialogue System/Scripts/MVC/Model/Data/Field.cs:351)
PixelCrushers.DialogueSystem.Field.SetValue (System.Collections.Generic.List`1 fields, System.String title, System.String value) (at Assets/Plugins/Pixel Crushers/Dialogue System/Scripts/MVC/Model/Data/Field.cs:369)
PixelCrushers.DialogueSystem.DialogueEntry.set_Title (System.String value) (at Assets/Plugins/Pixel Crushers/Dialogue System/Scripts/MVC/Model/Data/DialogueEntry.cs:138)
PixelCrushers.DialogueSystem.DialogueEditor.DialogueEditorWindow.DrawDialogueEntryFieldContents () (at Assets/Plugins/Pixel Crushers/Dialogue System/Scripts/Editor/Dialogue Editor/DialogueEditorWindowDialogueTreeSection.cs:544)
PixelCrushers.DialogueSystem.DialogueEditor.DialogueEditorWindow.DrawDialogueEntryInspector () (at Assets/Plugins/Pixel Crushers/Dialogue System/Scripts/Editor/Dialogue Editor/DialogueEditorWindowDialogueTreeSection.cs:899)
PixelCrushers.DialogueSystem.DialogueDatabaseEditor.DrawInspectorSelection () (at Assets/Plugins/Pixel Crushers/Dialogue System/Scripts/Editor/Dialogue Editor/DialogueDatabaseEditor.cs:186)
PixelCrushers.DialogueSystem.DialogueDatabaseEditor.OnInspectorGUI () (at Assets/Plugins/Pixel Crushers/Dialogue System/Scripts/Editor/Dialogue Editor/DialogueDatabaseEditor.cs:67)
UnityEditor.InspectorWindow.DoOnInspectorGUI (Boolean rebuildOptimizedGUIBlock, UnityEditor.Editor editor, Boolean wasVisible, UnityEngine.Rect& contentRect) (at C:/buildslave/unity/build/Editor/Mono/Inspector/InspectorWindow.cs:1625)
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
Image

Do you have solution for this? Thank you...
Last edited by ichisan on Thu Jan 31, 2019 8:48 am, edited 1 time in total.
User avatar
Tony Li
Posts: 22056
Joined: Thu Jul 18, 2013 1:27 pm

Re: Create linked nodes with code

Post by Tony Li »

Hi,

Use the Template class. If the script runs in the editor, you can use TemplateTools.LoadFromEditorPrefs() to get a Template class that uses any template fields you've set up in the Dialogue Editor's Templates section. Otherwise use Template.FromDefault() like the example below. This example creates a new database and adds a conversation with a START node and one actual node:

Code: Select all

// Create database:
var database = ScriptableObject.CreateInstance<DialogueDatabase>();

// Create a template, which provides helper methods for creating database content:
var template = Template.FromDefault();

// Create actors:
int playerID = template.GetNextActorID(database);
database.actors.Add(template.CreateActor(playerID, "Player", true));
int npcID = template.GetNextActorID(database);
database.actors.Add(template.CreateActor(npcID, "NPC", false));

// Create a conversation: [ID 0=START] --> [ID 1=Hello]
int conversationID = template.GetNextConversationID(database);
var conversationTitle = "My Conversation";
var conversation = template.CreateConversation(conversationID, conversationTitle);
conversation.ActorID = playerID;
conversation.ConversantID = npcID;
database.conversations.Add(conversation);

// START node: (Every conversation starts with a START node with ID 0)
var startNode = template.CreateDialogueEntry(0, conversation.id, "START");
node.ActorID = playerID;
node.ConversantID = npcID;
startNode.Sequence = "None()"; // START node usually shouldn't play a sequence.
conversation.dialogueEntries.Add(startNode);

// Actual dialogue node ("Hello") with ID 1: (could have used template.GetNextDialogueEntryID)
var helloNode = template.CreateDialogueEntry(1, conversation.id, string.Empty);
helloNode.ActorID = npcID; // NPC speaks this line.
helloNode.ConversantID = playerID;
helloNode.DialogueText = "Hello";
conversation.dialogueEntries.Add(helloNode);

// Link from START to Hello:
var link = new Link(conversation.id, startNode.id, conversation.id, node.id);
startNode.outgoingLinks.Add(link);

// And what the heck - might as well add it to the runtime environment and play it:
DialogueManager.AddDatabase(database);
DialogueManager.StartConversation(conversationTitle);
ichisan
Posts: 10
Joined: Thu Dec 07, 2017 12:38 am
Location: Indonesia

Re: Create linked nodes with code

Post by ichisan »

Thankyou Tony, it works. You help a lot :D
For anyone who have same problem, this my codes:

Code: Select all


using System.Collections.Generic;
using UnityEngine;
using PixelCrushers.DialogueSystem;
using System.Linq;

[ExecuteInEditMode]
public class AddchildDialogueManager : MonoBehaviour
{
    public bool execute = false;
    public DialogueDatabase database;
    public int conversationID = 0;
    public int numberCreate = 0;
    private int lastId = 0;

    // Update is called once per frame
    void Update()
    {
        if (execute && database.conversations.Any(x => x.id == conversationID))
        {
            Conversation conversation = database.conversations.Find(x => x.id == conversationID);
            List<DialogueEntry> entries = conversation.dialogueEntries;
            
            var template = Template.FromDefault();
           

            for (int i = 0; i < numberCreate; i++)
            {
                DialogueEntry lastEntry = entries[entries.Count - 1];
                int nextEntry = template.GetNextDialogueEntryID(conversation);
                var newNode = template.CreateDialogueEntry(nextEntry,conversation.id, string.Empty);
                if(database.actors.Any(x=>!x.IsPlayer))
                    newNode.ActorID = database.actors.Find(x=> !x.IsPlayer).id; // NPC speaks this line.
                else
                {
                    int npcID = template.GetNextActorID(database);
                    database.actors.Add(template.CreateActor(npcID, "NPC", false));
                    newNode.ActorID = npcID;
                }
                if (database.actors.Any(x => x.IsPlayer))
                    newNode.ConversantID = database.actors.Find(x=>x.IsPlayer).id;
                else
                {
                    int playerID = template.GetNextActorID(database);
                    database.actors.Add(template.CreateActor(playerID, "Player", true));
                    newNode.conversationID = playerID;
                }
                newNode.DialogueText = string.Empty;
                Rect newNodeRect = lastEntry.canvasRect;
                newNodeRect.y += 50;
                newNode.canvasRect = newNodeRect;
                entries.Add(newNode);
                
                var link = new Link(conversation.id,lastEntry.id, conversation.id, nextEntry);
                lastEntry.outgoingLinks.Add(link);
            }
            Debug.Log("Done");
        } else
        {
            Debug.Log("No data found");
        }
        execute = false;
    }
}

Cheers.
User avatar
Tony Li
Posts: 22056
Joined: Thu Jul 18, 2013 1:27 pm

Re: [Solved] Create linked nodes with code

Post by Tony Li »

Thanks for sharing the code!
Post Reply