效果展示
代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class NpcDialogue : MonoBehaviour
{
public GameObject dialoguePanel; // 显示对话的面板。
public TextMeshProUGUI dialogueText; // 显示实际对话内容的文本组件。
public string[] dialogue; // 包含对话行的字符串数组。
private int index; // 用于跟踪当前对话行的计数器。
public float wordSpeed; // 屏幕上单词显示速度的设定值。
public bool playerIsClose; // 一个布尔标志,指示玩家是否足够接近以与NPC互动。
public GameObject contButton; // 当对话显示时出现的“继续”按钮。
private bool typing = false; // 指示当前是否正在逐字显示对话。
private bool skipped = false; // 指示玩家是否跳过了逐字显示动画。
private bool seenStarterText = false; // 指示初始对话是否已经显示过。
public GameObject storeMenu; // 代表商店菜单的游戏对象。
void Update()
{
// 检查玩家是否按下了'E'键并且靠近了NPC。
if (Input.GetKeyDown(KeyCode.E) && playerIsClose)
{
// 如果初始文本还没有被查看。
if (!seenStarterText)
{
// 如果对话面板已经在激活状态,则停止所有协程,清空对话文本,关闭对话面板,并将索引重置为0。
if (dialoguePanel.activeInHierarchy)
{
StopAllCoroutines();
dialogueText.text = "";
dialoguePanel.SetActive(false);
index = 0;
}
// 否则,激活对话面板并开始逐字显示第一行对话。
else
{
dialoguePanel.SetActive(true);
StartCoroutine(Typing());
}
}
// 如果初始文本已经被查看,打开商店菜单。
else
{
storeMenu.SetActive(true);
}
}
// 检查玩家是否在对话面板激活状态下按下了空格键。
if (Input.GetKeyDown(KeyCode.Space) && dialoguePanel.activeInHierarchy)
{
// 如果没有正在进行逐字显示,则转到下一行。
if (!typing)
{
NextLine();
}
// 如果正在逐字显示,则跳过逐字显示动画。
else
{
skipped = true;
}
}
}
// 清除对话文本并重置索引的函数。
public void zeroText()
{
dialogueText.text = "";
index = 0;
dialoguePanel.SetActive(false);
}
// 逐字显示对话的协程。
IEnumerator Typing()
{
typing = true;
foreach (char letter in dialogue[index].ToCharArray())
{
dialogueText.text += letter;
// 等待一段时间后添加下一个字母。如果逐字显示被跳过,则不等待。
yield return new WaitForSeconds(wordSpeed * (skipped ? 0.01f : 1f));
}
typing = false;
skipped = false;
}
// 显示下一行对话的函数。
public void NextLine()
{
// 如果有更多对话行,增加索引并开始逐字显示下一行。
if (index < dialogue.Length - 1)
{
index++;
dialogueText.text = "";
StartCoroutine(Typing());
}
// 如果是最后一行对话,清除对话并打开商店菜单。
else
{
zeroText();
storeMenu.SetActive(true);
seenStarterText = true;
}
}
// 当NPC的2D触发器碰到另一个碰撞器时调用的函数。
private void OnTriggerEnter2D(Collider2D other)
{
// 检查玩家是否进入了触发区域。
if (other.CompareTag("Player"))
{
playerIsClose = true;
dialogueText.text = "";
}
}
// 当NPC的3D触发器碰到另一个碰撞器时调用的函数。
private void OnTriggerEnter(Collider other)
{
// 检查玩家是否进入了触发区域。
if (other.CompareTag("Player"))
{
playerIsClose = true;
dialogueText.text = "";
}
}
// 当NPC的3D触发器离开另一个碰撞器时调用的函数。
private void OnTriggerExit(Collider other)
{
// 检查玩家是否离开了触发区域。
if (other.CompareTag("Player"))
{
playerIsClose = false;
}
zeroText();
StopAllCoroutines();
}
}
具体操作过程