Unity implements dialogue control

Purpose: Create a script that can control the appearance of the dialog box and the content of the dialogue. When the character is close to the NPC, you can press the e key to proceed to the next dialogue.

Additional content: If the mission system is added, when receiving a mission, the player clicks e multiple times to skip the dialogue without understanding the mission requirements. Therefore, when approaching the NPC again and pressing e, the mission requirements should be repeated, that is, the last sentence of the text is repeated . In addition, an NPC may have multiple sets of text content, and it must be able to switch between each content.

Demo video

plan:

1. Save conversation content

Use xml file storage, reason: convenience, the text content corresponding to a role belongs to its sub-elements, and the content can be read by citing the library provided by c#. In addition, there are already tutorials using xml to facilitate implementation. I would like to thank Zhihu user 5hT89p.

Tutorial on creating a dialogue system using Unity - Zhihu (zhihu.com)

<?xml version="1.0" encoding="UTF-8"?>
<Root>
<girl>
<suit>
<line>hello</line>
<line>come here</line>
<line>go to fight a monster</line>
</suit>
<suit>
<line>you win!</line>
<line>go to open the box</line>
<line>just continue to adventure,bye</line>
</suit>
</girl>
</Root>

There are two sets of dialogue content in the above text, one is when accepting the task:

hello

to eat

go to fight a monster

Another set is after completing the task:

you win!

go to open the box

just continue to adventure,bye

Thanks to the noob tutorial for letting me understand xml and be able to write the above code

XML Elements | Newbie Tutorial (runoob.com)

2.Control of conversation content

First, the text must be read from xml and stored in the two-dimensional array content. The reason for the two dimensions is that an NPC has multiple sets of dialogue content. One set of dialogues occupies one line, and multiple sets require multiple lines.

private List<List<string>> content=new List<List<string>>();
void Start()
    {
        XmlDocument xml = new XmlDocument();
        xml.Load(Application.dataPath + "/dialog/content.xml");        
        XmlNode xmlNode = xml.SelectSingleNode("Root" + "/" + transform.name);       
        foreach (XmlNode x1 in xmlNode.ChildNodes)
        {
            List<string> my = new List<string>();
            foreach (XmlNode x2 in x1.ChildNodes)
            {
                my.Add(x2.InnerText);
            }
            content.Add(my);                
        }        
    }

Second, switch the text content and display it into the dialog box .

There are two points to consider. First, the dialog box will only be displayed when the character is close, so distance judgment needs to be added to the code. Second, some NPCs may always be able to talk, but some NPCs can only talk once and can no longer interact. Therefore, a public flag needs to be set to distinguish these two types of NPCs.

IEnumerator nextWord()
    {
        if (Input.GetKeyDown(KeyCode.F))
        {
            nextOrNot = true;
        }
        if (Input.GetButtonDown("Submit") && Mathf.Abs(player.transform.position.x - transform.position.x)<effectDist)
        {         
            if(nextOrNot)
            {                
                whichSuit++;
                whichString = 0;
                nextOrNot = false;
            }
            if (whichSuit < content.Count)
            {
                if (whichString < content[whichSuit].Count)
                {
                    panel.SetActive(true);
                    words.enabled = true;
                    words.text = content[whichSuit][whichString];
                    whichString++;
                }
                else
                {
                    panel.SetActive(false);
                    words.enabled = false;
                    if (alwaysHasWord)
                    {                        
                        whichString--;
                    }
                    else
                    {
                        this.enabled = false;                      
                    }                    
                }
            }
            else
            {
                panel.SetActive(false);
                words.enabled = false;
            }
            yield return new WaitForSeconds(.2f);
        }
        else if(Mathf.Abs(player.transform.position.x - transform.position.x) > effectDist)
        {
            panel.SetActive(false);
            words.enabled = false;
        }
        yield return null;
    }

In order to find the specific sentence to be said, set the int type whichSuit and whichString as the index of the two-dimensional array to locate what to say. alwaysHasWord is the flag that determines whether the character repeats the last sentence. In order to be able to repeat the last sentence, Therefore, if alwaysHasWord is true, then subtract 1 from the index, which is still within the valid range of the two-digit array (actually the string corresponding to the last column of the row, that is, the last sentence).     

 Why use coroutines?

Because when writing scripts, you can always find that getButtonDown executes more than one frame, which will cause the text to be continuously skipped. Therefore, using the coroutine, after pressing e, you always have to wait 0.2s before executing nextWord() again. , jump to the next sentence                                                                 

Guess you like

Origin blog.csdn.net/qq_16198739/article/details/126650482