如何使用对话的名称作为触发对话而不是使用索引的触发器?

时间:2019-04-12 21:20:02

标签: c# unity3d

在管理器脚本中,我有一个启动对话名称的方法:StartDialogue:

https://www.overpass-api.de/api/interpreter?data=area[%22name%22=%22Nicaragua%22][%22admin_level%22=%222%22]-%3E.boundaryarea;(node[%22type%22=%22route%22][%22route%22=%22bus%22](area.boundaryarea);way[%22type%22=%22route%22][%22route%22=%22bus%22](area.boundaryarea);%3E;relation[%22type%22=%22route%22][%22route%22=%22bus%22](area.boundaryarea);%3E%3E;);out%20meta;

然后在触发脚本中,我有一个方法名称TriggerDialogue,它获取索引号。例如索引0,它将开始第一个对话的对话。但实际上,这只是从“对话列表”中开始第一次对话。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class DialogueManager : MonoBehaviour
{
    public Text dialogueText;
    public Text nameText;
    public float sentencesSwitchDuration;
    public bool animateSentenceChars = false;
    public GameObject canvas;
    public static bool dialogueEnded = false;
    public DialogueTrigger trigger;

    private Queue<string> sentence;

    // Use this for initialization
    void Start()
    {
        sentence = new Queue<string>();
    }

    public void StartDialogue(Dialogue dialogue)
    {
        canvas.SetActive(true);

        nameText.text = dialogue.name;

        sentence.Clear();
        foreach (string sentence in dialogue.sentences)
        {
            this.sentence.Enqueue(sentence);
        }

        DisplayNextSentence();
    }

    public void DisplayNextSentence()
    {
        if (this.sentence.Count == 0)
        {
            EndDialogue();
            return;
        }

        string sentence = this.sentence.Dequeue();
        dialogueText.text = sentence;

        StopAllCoroutines();
        StartCoroutine(DisplayNextSentenceWithDelay(sentence));
    }

    public IEnumerator DisplayNextSentenceWithDelay(string sentence)
    {
        if (animateSentenceChars)
        {
            dialogueText.text = "";
            foreach (char letter in sentence.ToCharArray())
            {
                dialogueText.text += letter;
                yield return null;
            }
        }

        yield return new WaitForSeconds(sentencesSwitchDuration);
        DisplayNextSentence();
    }

    private void EndDialogue()
    {
        dialogueEnded = true;
        if (trigger.dialogueNum == trigger.conversations[trigger.dialogueIndex].Dialogues.Count)
            canvas.SetActive(false);
        Debug.Log("End of conversation.");
    }
}

然后我有另外两个小类:

对话:

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;

[ExecuteInEditMode]
public class DialogueTrigger : MonoBehaviour
{
    public List<Conversation> conversations = new List<Conversation>();
    //public List<Dialogue> dialogue = new List<Dialogue>();

    [HideInInspector]
    public int dialogueNum = 0;

    [HideInInspector]
    public int dialogueIndex = 0;

    private bool triggered = false;
    private List<Dialogue> oldDialogue;
    private bool activateButton = false;

    public void TriggerDialogue(int dialogueIndex)
    {
        this.dialogueIndex = dialogueIndex;

        if (conversations.Count > 0 &&
            conversations[dialogueIndex].Dialogues.Count > 0)
        {
            if (triggered == false)
            {
                if (FindObjectOfType<DialogueManager>() != null)
                {
                    FindObjectOfType<DialogueManager>().StartDialogue(conversations[dialogueIndex].Dialogues[dialogueNum]);
                    dialogueNum += 1;
                }
                triggered = true;
            }
        }
    }

    private void Update()
    {
        ButtonActivation();

        if (DialogueManager.dialogueEnded == true)
        {
            if (dialogueNum == conversations[dialogueIndex].Dialogues.Count)
            {
                return;
            }
            else
            {
                FindObjectOfType<DialogueManager>().StartDialogue(conversations[dialogueIndex].Dialogues[dialogueNum]);
                DialogueManager.dialogueEnded = false;
                dialogueNum += 1;
            }
        }
    }

    public bool ActivateButton()
    {
        return activateButton;
    }

    private void ButtonActivation()
    {
        if (ConversationsChecks() == true)
        {
            foreach (string sentence in conversations[dialogueIndex].Dialogues[dialogueNum].sentences)
            {
                if (sentence != "")
                {
                    activateButton = true;
                }
                else
                {
                    activateButton = false;
                }
            }
        }
        else
        {
            activateButton = false;
        }
    }

    public void SaveConversations()
    {
        string jsonTransform = JsonHelper.ToJson(conversations.ToArray(), true);
        File.WriteAllText(@"d:\json.txt", jsonTransform);
    }

    public void LoadConversations()
    {
        string jsonTransform = File.ReadAllText(@"d:\json.txt");
        conversations.Clear();
        conversations.AddRange(JsonHelper.FromJson<Conversation>(jsonTransform));
    }

    private bool ConversationsChecks()
    {
        bool IsConversationsReady = false;

        if (conversations.Count > 0 &&
            conversations[dialogueIndex].Dialogues.Count > 0 &&
            conversations[dialogueIndex].Dialogues[dialogueNum].sentences.Count > 0 &&
            conversations[dialogueIndex].Dialogues[dialogueNum].name != "" &&
            conversations[dialogueIndex].name != "")
        {
            IsConversationsReady = true;
        }
        else
        {
            IsConversationsReady = false;
        }

        return IsConversationsReady;
    }
}

对话:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class Dialogue
{
    [Tooltip("Dialogue Name")]
    public string name;

    [TextArea(1, 10)]
    public List<string> sentences = new List<string>();
}

所以现在当我想开始对话时,我像下面的示例一样调用TriggerDialogue方法:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class Conversation
{
    [Tooltip("Conversation Name")]
    public string name;

    public List<Dialogue> Dialogues = new List<Dialogue>();
}

相反,我想做这样的事情:

dialogueTrigger.TriggerDialogue(0);

dialogueTrigger.StartConversation("Opening Scene");

这是示例对话和对话的屏幕截图:

Conversations

例如,如果我想在游戏中的某个地方开始第一次对话,我会这样做:

dialogueTrigger.StartConversation("The last conversation");

它将开始“开幕”对话中的对话。

使用索引可以正常工作,但我想通过对话名称开始对话,这会更容易。

1 个答案:

答案 0 :(得分:0)

鉴于您正在使用List<T>,如果您不再使用索引来获取所需的项目,则每次都需要枚举集合以找到相同的项目。您在这里可以做的最好的事情就是将数据结构更改为Dictionary,以便您可以通过Key搜索它,从而避免性能下降。为了避免不得不记住您在对话中使用的名字,也许最​​好使用枚举。

因此,创建枚举:

public enum SceneConversations
{
    OpeningScene = 1,
    // ...
}

并开始使用

public class DialogueTrigger : MonoBehaviour
{
    public Dictionary<SceneConversations, Conversation> conversations = new Dictionary<SceneConversations, Conversation>();

然后您可以使用

public void StartConversation(SceneConversations conversationWanted) {}

并用

调用
dialogueTrigger.StartConversation(SceneConversations.OpeningScene);

如果我没记错的话,这样做还有一个好处,就是Unity会向您显示一个SceneConversations可能值的下拉列表,因此也更易于处理。