0
\$\begingroup\$

im trying to make a dialogue/monologue system using XML to direct the flow. all is working well and good but i have an issue with the dialogue setup , My issue is that although i can change the index of the nodes and read them unless they have the same structure it throws a null reference error exception. the xml is this :

<?xml version="1.0" encoding="utf-8"?>
<CharacterCollection>
    <CharactersDialogue>
        
        <Character name="Bob">
            <Name>Bob</Name>
            <Intro>
                Hello, my name is Bob! Lets test this dialogue! What do you think Stratos??
                <Response next="Swap">Yes!</Response>
            </Intro>    
        </Character>
        
        <Character name="Stratos">
            <Name>Stratos</Name>
            <Intro>
                Oh yes yes i very much like to! can we start now?
                <Response next="0">Yes!</Response>
                <Response next="Quit">Another time!</Response>
            </Intro>
            <Tree0>
                Great! onwards we go!!
                <Flow goto ="Quit">quit</Flow>
            </Tree0>
        </Character>    
        
    </CharactersDialogue>
</CharacterCollection>

now the issue with this is that when i reach the second character node and try to go to Tree0 then its when it fires the error but if i have a Tree0 element in the first node all is well.

Now the dialogue system is pretty big so i will post here the parts that generate the error!

    XmlNodeList PrepareXML(string fileName, string path)
    {
        var textFile = Resources.Load(fileName) as TextAsset;

        XmlDocument xmlDoc = new XmlDocument();
        string xml = textFile.text;
        xmlDoc.LoadXml(xml);
        XmlNodeList nodes;
        nodes = xmlDoc.SelectNodes(path);
        return nodes;
    }

    public string ReadXml(string fileName, string path, string node, int id)
    {
        XmlNodeList nodes = PrepareXML(fileName, path);
        return nodes[id].SelectSingleNode(node).FirstChild.Value;
    }

    public string[] ReadSubnodes(string fileName, string path, int id)
    {
        XmlNodeList nodes = PrepareXML(fileName, path);

        XmlNodeList subnodes = nodes[id].SelectNodes("Response"); // this is the error call
        string[] choiceDescs = new string[subnodes.Count];
        choiceAttributes = new string[subnodes.Count];

        for (int i = 0; i < subnodes.Count; i++)
        {
            choiceAttributes[i] = subnodes[i].SelectSingleNode("@next").Value;
            choiceDescs[i] = subnodes[i].FirstChild.Value;
        }
        return choiceDescs;
    }

And finally this is the dialogue controller where i declare which id to read from the path and all the flow

 public void ConversationStart()
    {
        text = reader.ReadXml(file, path, "Name", id);
        actorImageString = reader.ReadActorName(file, path, id);
        foreach (var item in actorsInventory.actors)
        {
            if (item.Name == actorImageString)
            {
                dialogueManager.actorImage.sprite = item.actorImage;
            }
        }

        dialogueManager.actorName.text = text.Trim();

        text = reader.ReadXml(file, path, initialXmlTag, id);
        dialogueManager.dialogueText.text = text.Trim();
        GetChoices("/" + initialXmlTag);
    }

    void GetChoices(string location)
    {
        dialogueManager.GetChoices(reader.ReadSubnodes(file, path + location, id), 
        reader.ChoiceAttributes);
        dialogueManager.PassChoice += ConversationUpdate;
    }


    void ConversationUpdate(string lineTree)
    {
        dialogueManager.PassChoice -= ConversationUpdate;

        if (lineTree == "TreeQuit")
        {
            EndConversation();

        }
        else if (lineTree == "TreeSwap")
        {
            id++;
            ConversationStart();
        }
        else
        {
            text = reader.ReadXml(file, path, lineTree, id);
            dialogueManager.dialogueText.text = text.Trim();
            GetChoices("/" + lineTree); // here is when the error is thrown
        }
        
    }

     // this is the buttons generated through the xml once i tap it it invokes a delegate

     public delegate void ChoicePasser(string lineTree);
     public ChoicePasser PassChoice;

     void clickAction(string attribute)
    {
        currentButtons = null;
        PassChoice?.Invoke(subTree + attribute);
    }

This is pretty much the whole system apart from the generation of the choices buttons based on the integer in the xml keys? dont know if im calling them right. the issue is that if i run the id 0 (first Character) and go over to 1 on Swap once i select the choice to go to Tree0 it throws a null reference error, but if i swap the Characters (make Character Stratos id 0) and run it it goes just fine! now if i also add the Tree0 in the node 0 it also works fine but i dont want to have to make all characters have the same number of selections!

Any help is appreciated as im new to XML and am going through trial and error!

\$\endgroup\$
2
  • \$\begingroup\$ My usual approach to dealing with data in XML files is to first parse the whole XML file into my own object representation and then work with those objects. Many programming languages have libraries which allow you to deserialize XML nodes into classes and vice-versa. One critical advantage of this architecture is that it allows you to check all the content of the XML file for plausibility the moment you load it, not the moment you use it. \$\endgroup\$
    – Philipp
    Nov 3, 2021 at 13:11
  • \$\begingroup\$ i see thank you , i did research it a bit but yeah i might need to read more about it in order to fully get it and see how to add the rest of the command elements i have apart from the Response and Flow. But other than that you wouldnt happen to have an idea as to why it throws the error ? i mean it should be working as i reading each node separately \$\endgroup\$
    – stratos la
    Nov 3, 2021 at 13:37

0

You must log in to answer this question.

Browse other questions tagged .