using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
[System.Serializable]
public class DialogueOption
{
public string text;
public string[] response;
public UnityEvent action;
}
public class DialogueSystem : MonoBehaviour
{
// 单例实现
private static DialogueSystem _instance;
public static DialogueSystem Instance => _instance ??= CreateInstance();
private static DialogueSystem CreateInstance()
{
var prefab = Resources.Load<GameObject>("DialogueSystem/DialogueCanvas");
var instance = Instantiate(prefab).GetComponent<DialogueSystem>();
DontDestroyOnLoad(instance.gameObject);
return instance;
}
// UI组件引用
[Header("UI Components")]
public Text nameText;
public Text dialogueText;
public Button continueButton;
public Image avatarImage;
public Button[] optionButtons;
public GameObject optionsPanel;
// 对话状态
private string[] messages;
private int currentMessageIndex;
private List<DialogueOption> currentOptions;
void Start() => continueButton.onClick.AddListener(ShowNextMessage);
/// <summary>显示对话</summary>
public void ShowDialogue(string name, string[] msgs, string avatarPath, List<DialogueOption> options = null)
{
nameText.text = name;
avatarImage.sprite = Resources.Load<Sprite>(avatarPath);
messages = msgs;
currentMessageIndex = 0;
currentOptions = options;
gameObject.SetActive(true);
ShowNextMessage();
}
/// <summary>显示下一条消息</summary>
private void ShowNextMessage()
{
optionsPanel.SetActive(false);
if (currentMessageIndex < messages.Length)
{
dialogueText.text = messages[currentMessageIndex++];
continueButton.gameObject.SetActive(true);
}
else
{
ShowOptions();
}
}
/// <summary>显示选项面板</summary>
private void ShowOptions()
{
if (currentOptions == null || currentOptions.Count == 0)
{
gameObject.SetActive(false);
return;
}
dialogueText.text = "你现在要做什么?";
continueButton.gameObject.SetActive(false);
optionsPanel.SetActive(true);
for (int i = 0; i < optionButtons.Length; i++)
{
var button = optionButtons[i];
bool hasOption = i < currentOptions.Count;
button.gameObject.SetActive(hasOption);
if (hasOption)
{
var option = currentOptions[i];
button.GetComponentInChildren<Text>().text = option.text;
button.onClick.RemoveAllListeners();
button.onClick.AddListener(() => OnOptionSelected(option));
}
}
}
/// <summary>处理选项选择</summary>
private void OnOptionSelected(DialogueOption option)
{
option.action?.Invoke();
if (option.response?.Length > 0)
ShowDialogue(nameText.text, option.response, avatarImage.sprite.name);
else
gameObject.SetActive(false);
}
}
using System.Collections.Generic;
using UnityEngine;
public class ContinuousDialogueSystem : MonoBehaviour
{
// ================= 对话状态管理 =================
private int currentDialogueIndex = 0;
private bool isInDialogue = false;
// ================= 连续对话数据结构 =================
[System.Serializable]
public class DialogueSequence
{
public string speaker; // 说话者名称
public string avatarPath; // 头像资源路径
public string[] messages; // 对话消息数组
public List<DialogueOption> options; // 对话选项
}
[System.Serializable]
public class DialogueOption
{
public string text; // 选项文本
public string[] response; // 选择后的NPC回应
public int nextSequenceIndex; // 下一个对话序列的索引
}
// ================= 对话剧本 =================
public List<DialogueSequence> dialogueSequences = new List<DialogueSequence>
{
// 序列0: 初次见面
new DialogueSequence {
speaker = "星之卡比",
avatarPath = "Avatars/Kirby",
messages = new [] {
"你好,旅行者!",
"欢迎来到梦幻岛!",
"最近森林里发生了奇怪的事情..."
},
options = new List<DialogueOption> {
new DialogueOption {
text = "询问详情",
response = new [] {"魔法果实一夜之间全消失了!", "这太不寻常了..."},
nextSequenceIndex = 1
},
new DialogueOption {
text = "表示愿意帮忙",
response = new [] {"太好了!我就知道能找到帮手!", "请跟我来..."},
nextSequenceIndex = 2
},
new DialogueOption {
text = "询问背景故事",
response = new [] {"很久以前,梦幻岛被黑暗势力侵袭...", "我们需要守护这片土地!"},
nextSequenceIndex = 0
}
}
},
// 序列1: 调查开始
new DialogueSequence {
speaker = "星之卡比",
avatarPath = "Avatars/Kirby_Serious",
messages = new [] {
"我们发现了可疑的脚印",
"看起来像是暗影生物的痕迹",
"它们可能藏在森林深处..."
},
options = new List<DialogueOption> {
new DialogueOption {
text = "提议追踪脚印",
response = new [] {"好主意!让我们小心前进..."},
nextSequenceIndex = 3
},
new DialogueOption {
text = "询问更多线索",
response = new [] {"昨晚守夜人听到了奇怪的声响...", "还有闪烁的紫色光芒"},
nextSequenceIndex = 1
},
new DialogueOption {
text = "返回村庄准备",
response = new [] {"明智的选择,我们需要更好的装备", "我在村口等你..."},
nextSequenceIndex = 4
}
}
},
// 序列2: 直接行动
new DialogueSequence {
speaker = "星之卡比",
avatarPath = "Avatars/Kirby_Determined",
messages = new [] {
"勇敢的决定!",
"拿上这把星光短剑",
"它会保护你免受黑暗侵蚀"
},
options = new List<DialogueOption> {
new DialogueOption {
text = "接受武器",
response = new [] {"愿星光指引你的道路!", "我们出发吧..."},
nextSequenceIndex = 3
},
new DialogueOption {
text = "询问使用方法",
response = new [] {"只需将剑尖指向黑暗生物...", "星光会自动净化它们"},
nextSequenceIndex = 2
}
}
}
// 可以继续添加更多序列...
};
// ================= 对话控制 =================
void Update()
{
// 按F键开始对话
if (Input.GetKeyDown(KeyCode.F) && !isInDialogue)
{
StartDialogue();
}
}
void StartDialogue()
{
isInDialogue = true;
ShowCurrentSequence();
}
void ShowCurrentSequence()
{
DialogueSequence current = dialogueSequences[currentDialogueIndex];
DialogueSystem.Instance.ShowDialogue(
current.speaker,
current.messages,
current.avatarPath,
current.options
);
}
// ================= 选项回调 =================
// 当玩家选择选项时调用
public void OnOptionSelected(int optionIndex)
{
if (currentDialogueIndex < dialogueSequences.Count)
{
DialogueSequence current = dialogueSequences[currentDialogueIndex];
if (optionIndex < current.options.Count)
{
DialogueOption selectedOption = current.options[optionIndex];
// 显示选择后的回应
DialogueSystem.Instance.ShowResponse(
current.speaker,
selectedOption.response,
current.avatarPath
);
// 设置下一个对话序列
currentDialogueIndex = selectedOption.nextSequenceIndex;
// 延迟后继续下一个对话
StartCoroutine(ContinueAfterDelay(1.5f));
}
}
}
private System.Collections.IEnumerator ContinueAfterDelay(float delay)
{
yield return new WaitForSeconds(delay);
ShowCurrentSequence();
}
}
这是我的脚本我现在想用对话树的方式完成纯对话游戏