DIALOGUE BRANCH CREATION?

Script is giving me headache and bugs(like index out of bound and chaotic answers and replies)
It’s just changing text components for now really. Relevant methods:

public string[] dialogueBranch1;//changing textbox
        public string[] dialogueBranch2;
        public string[] dialogueBranch3;
        int branch1Index = 0;
        int branch2Index = 0;
        int branch3Index = 0;
        public string[] answerBranch1;
        public string[] answerBranch2;
        public string[] answerBranch3;

public void ChoiceOption1()
    {
        textBox.GetComponent<Text>().text = dialogueBranch1[branch1Index];
        choiceMade = 1;
    }
    public void ChoiceOption2()
    {
        textBox.GetComponent<Text>().text = dialogueBranch2[branch2Index];
        choiceMade = 2;
    }
    public void ChoiceOption3()
    {
        textBox.GetComponent<Text>().text = dialogueBranch3[branch3Index];
        choiceMade = 3;
       
    }
        public void ChoiceExit()
        {
            HideDialogue();
            ShowCanvas();
            isTalking = false;
            
        }

        private void Update()
        {
            if (isTalking == true)
            {
                Cursor.lockState = CursorLockMode.None;
                Cursor.visible = true;
            }
            else
            {
                Cursor.lockState = CursorLockMode.Locked;
                Cursor.visible = false;
            }


            if (choiceMade == 1)
            {
                ClickChanger(choice1, answerBranch3[branch1Index]);
            }
            if (choiceMade == 2)
            {
                
                ClickChanger(choice2, answerBranch2[branch2Index]);

            }
            if (choiceMade == 3)
            {
                ClickChanger(choice3, answerBranch3[branch3Index]);
                
            }
        }
private void ClickChanger(GameObject buttonGameObject, string txt)
        {
            //print a new text on button and text box(replace buttons)
            buttonGameObject.GetComponent<Text>().text = txt;
            buttonGameObject.GetComponent<Button>().onClick.AddListener(ChangeTextForChoice);
        }
        void ChangeTextForChoice()
        {
            if(choiceMade == 1)
            {
                SetText(answerBranch1[branch1Index]);
                if (branch1Index <= dialogueBranch1.Length)
                {
                    branch1Index++;
                }
                else
                {
                    return;
                }
            }
            if (choiceMade == 2)
            {
                SetText(answerBranch1[branch2Index]);
                if (branch2Index <= dialogueBranch2.Length)
                {
                    branch2Index++;
                }
                else
                {
                    return;
                }
            }
            if (choiceMade == 3)
            {
                SetText(answerBranch1[branch3Index]);
                if (branch3Index <= dialogueBranch3.Length)
                {
                    branch3Index++;
                }
                else
                {
                    return;
                }
            }

            //will change it
        }

        void SetText(string txt)
        {
            textBox.GetComponent<Text>().text = txt;
        }

Maybe I should use dictionaries?

Here ya go, this is from a pet project involving some visual novel jazz. I dont have time to really clean it up but, the concepts shown should help you.

Define dialogues and responses as structs, basically. Then, the number of options or responses or whatever can be dynamically defined in the editor.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ConversationHandler : MonoBehaviour
{
    public Transform dialoguePanel;
    public Transform responsePanel;
    public GameObject ourOptionPrefab;
    public GameObject responseDialoguePrefab;
    //define the struct for a dialogue option
    [System.Serializable]
    public struct dialogueOption
    {
        public string text;
        public int convo;
        public int response;
        public bool onlyShowOnce;

        public bool branchResponse;
        responseDialogue singleResponse;


        
    }
    [System.Serializable]
    public struct responseDialogue
    {
        public string text;
        public List<int> responses;
        public int actorImage;
    }
    [System.Serializable]
    public struct actor
    {
        public MeshRenderer image; 
        public List<Texture> graphics;
    }
    [System.Serializable]
    public struct conversation
    {
        public string convoName;
        public actor main_actor;
        public List<responseDialogue> responses;
        public List<dialogueOption> dialogues;
    }

    public List<conversation> conversations;

    
    public int testConvo;
    public void PopGUI(int convo)
    {
        Respond(0, 0);


    }

    public void ClearScreen()
    {

        /*
        foreach (Transform child in dialoguePanel)
        {
            print("Destroying " + child.name);
            DestroyImmediate(child.gameObject);
        }
        foreach (Transform child in responsePanel)
        {
            print("Destroying " + child.name);
            DestroyImmediate(child.gameObject);
        }
       */


        int childs = dialoguePanel.childCount;
        for (int i = childs - 1; i >= 0; i--)
        {
            DestroyImmediate(dialoguePanel.GetChild(i).gameObject);
        }


        int childs1 = responsePanel.childCount;
        for (int i = childs1 - 1; i >= 0; i--)
        {
            DestroyImmediate(responsePanel.GetChild(i).gameObject);
        }
    }


    
    public void Respond(int convo, int dOption)
    {
        print("Responding for option " + dOption + " in convo " + convo);
        dialogueOption option = conversations[convo].dialogues[dOption];
        print("option is " + option.text);
        //this function needs to clear the currently displayed things
        ClearScreen();
        //okay, the dialogue options and response options are destroyed.
        //for the option given, load the response
        responseDialogue showResponse = conversations[convo].responses[option.response];
        GameObject newResponse = Instantiate(responseDialoguePrefab, responsePanel);
        newResponse.GetComponentInChildren<Text>().text = showResponse.text;
        for (int i = 0; i < (showResponse.responses.Count); i++) {
            print(i);
            
            //  Debug.Break();
            GameObject newOption = Instantiate(ourOptionPrefab, dialoguePanel);
            print("new Option name " + newOption.name);
            DialogueOption dialogue = newOption.GetComponent<DialogueOption>();
            dialogue.keyPress = i + 1;
            dialogue.option = conversations[convo].dialogues[showResponse.responses*];*

dialogue.GetComponentInChildren().text = dialogue.option.text + “./” +i;

if (i >= showResponse.responses.Count)
{

print(“wat”);
}
// DestroyImmediate(newOption);
}

//okay here we should be able to set the actor for this conversation to have a new texture

MeshRenderer rend = conversations[convo].main_actor.image;
Material mat = rend.sharedMaterial;
mat.mainTexture = conversations[convo].main_actor.graphics[showResponse.actorImage];
rend.sharedMaterial = mat;
conversations[convo].main_actor.image.material = rend.material;

}

public void TestPaths()
{/*
for (int c = 0; c<conversations.Count; c++)
{
conversation convo = conversations
```c
*;
for (int r = 0; r < convo.responses.Count; r++)
{
responseDialogue response = convo.responses[r];
bool accessable = false;
foreach(int i in response.responses)
{
if (i == r)
{
accessable = true;
}

                }
                if (!accessable)
                {
                    print("Not accessable on response " + r);
                }

            }

        
        }*/


        foreach(conversation convo in conversations)
        {
            bool test = false;
            for (int r = 0; r<convo.responses.Count; r++)
            {
                bool accessible = false;
                //foreach (int rt in convo.responses[r].responses)
               // {
                   // if (t.response == )
                   //is this convo accessile from any dialogue?
                   //does r match the resonse for any dialogue?

                        for (int d = 0; d < convo.dialogues.Count; d++)
                        {
                            print("testing response " + r + " across dialogue " + d);
                               if(convo.dialogues[d].response == r)
                               {
                                   accessible = true;
                                   print("dialogue " + d+ "  matched response "+ r + " for " +  convo.dialogues[d].response);
                               }

                           // dialogueOption t = convo.dialogues[d];


                            //for each of the dialogues from each response,
                            //run through
                            /*
                          foreach(int t in convo.responses[r].responses)
                            {
                                if (t == r)
                                    accessible = true;

                            }*/

                        }
                //}

                if (!accessible)
                {
                    print("Warning! No dialogues point to this response:  " + r);
                    test = true;
                }


            }
            if (!test)
            {
                print("This conversation passed all path checks: " + convo.convoName);
            }


        }
    }



}*

```