c# - Unity中的NPC对话系统
问题描述
在过去的几天里,我一直在努力让对话系统正常工作,但我遇到了一些问题。第一个问题是我需要在输入文本时按下按钮才能在进入下一个句子之前立即完成,当我尝试它时出现了一些奇怪的错误,所以我恢复了它。我一直遇到的第二个问题是,当我复制 NPC 并更改第二个 NPC 的对话时,他们都只是说第一个 NPC 的对话设置为什么。
目前,我在玩家的侧面有一个碰撞器,当玩家的侧面碰撞器在按下空格键的同时接触到 NPC 时,它会触发对话。这是我的代码:
播放器脚本:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : Character
{
public BasicNPCPrototype NPCPrototype;
private bool nearNPC = false;
// Use this for initialization
protected override void Start()
{
// This needs to be here because the Override normally would override the Character Start function so we have this here to tell the Character Start function to go
base.Start();
}
// Update is called once per frame
protected override void Update() // Because the parent script (The Character script) is using protected virtual update it will Override the local update function (This one) so you have to write protected override to make sure they both run
{
// Call the GetInput Function
GetInput();
CheckIfNear();
// This needs to be here because the Override normally would override the Character Update function so we have this here to tell the Character Update function to go
base.Update();
}
void GetInput()
{
// If the player is active (playerActive is a protected bool in the "Character" script)
if(playerActive)
{
// Normalize "direction" so moving in both directions won't speed up the character (May not be nessisary when using Input.GetAxis, Needs testing)
direction = Vector2.zero;
// Get the horizontal Axis and put in the X value of "direction"
direction.x = Input.GetAxisRaw("Horizontal");
// Get the Vertical Axis and put in the Y value of "direction"
direction.y = Input.GetAxisRaw("Vertical");
}
}
// When the players trigger collider touches somthing
void OnTriggerEnter2D(Collider2D collision)
{
// Check to see if it has the "NPC" tag
if(collision.tag == "NPC")
{
// Set "nearNPC" bool to tue
nearNPC = true;
}
}
// When the players trigger collider exits somthing
void OnTriggerExit2D(Collider2D collision)
{
// Check to see if it has the "NPC" tag
if (collision.tag == "NPC")
{
// Set "nearNPC" bool to false
nearNPC = false;
}
}
private void CheckIfNear()
{
// If nearNPC bool is true
if (nearNPC == true)
{
// If the "Jump" Keybind is press
if (Input.GetButtonUp("Jump"))
{
// Call the Speak function in the NPCPrototype script
NPCPrototype.Speak();
}
}
}
}
NPC脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BasicNPCPrototype : MonoBehaviour
{
public Dialogue dialogue;
// Use this for initialization
void Start ()
{
}
// Update is called once per frame
void Update ()
{
}
public void Speak()
{
// Call the "StartDialogue" function in the DialogueManager and pass in our dialogue variable
FindObjectOfType<DialogueManager>().StartDialogue(dialogue);
}
}
这是我的对话管理器:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class DialogueManager : MonoBehaviour
{
public float waitBeforeDisable = 1f;
public GameObject dialogueBox;
public Text nameText;
public Text dialogueText;
public Animator animator;
private Queue<string> sentences;
private bool conversationActive = false;
// Use this for initialization
void Start()
{
//dialogueBox.SetActive(false);
sentences = new Queue<string>();
}
public void StartDialogue(Dialogue dialogue)
{
if (conversationActive == false)
{
dialogueBox.SetActive(true);
conversationActive = true;
animator.SetBool("isOpen", true);
nameText.text = dialogue.name;
sentences.Clear();
foreach (string sentence in dialogue.sentences)
{
sentences.Enqueue(sentence);
}
DisplayNextSentence();
}
if (conversationActive == true)
{
DisplayNextSentence();
}
}
public void DisplayNextSentence()
{
if (sentences.Count == 0)
{
EndDialogue();
return;
}
string sentence = sentences.Dequeue();
StopAllCoroutines();
StartCoroutine(TypeSentence(sentence));
}
void EndDialogue()
{
animator.SetBool("isOpen", false);
StartCoroutine("DisableDialogueBox");
conversationActive = false;
}
IEnumerator TypeSentence(string sentence)
{
dialogueText.text = "";
foreach (char letter in sentence.ToCharArray())
{
dialogueText.text += letter;
yield return null;
}
}
IEnumerator DisableDialogueBox()
{
yield return new WaitForSeconds (waitBeforeDisable);
dialogueBox.SetActive(false);
}
}
我对编码很陌生,如果我能得到一些帮助,那就太好了!如果您对我的问题有任何疑问,请随时提问。
解决方案
你没有改变你的NPCPrototype
参考
你在哪里设置 NPCPrototype 的值?– Draco18s
@Draco18s 在检查员中 – Ultra Gamer
因为您将它设置在检查器中(而不是其他任何地方),所以它永远不会改变。如果您希望对话来自特定 NPC,则需要在“我在附近吗?”时从该 NPC 获取组件。检查/碰撞。例如。:
void OnTriggerEnter2D(Collider2D collision)
{
// Check to see if it has the "NPC" tag
if(collision.tag == "NPC")
{
// Set "nearNPC" bool to tue
nearNPC = true;
NPCPrototype = collision.gameObject.GetComponent<BasicNPCPrototype>();
}
}
推荐阅读
- pycharm - 在 Ubuntu 上运行 Odoo 时出现 Odoo Pycharm 错误
- python - 如果屏幕上有像素,Python会播放声音
- javafx - 让 fileChooser 在舞台上工作时出现问题,不确定如何设置正确的舞台?
- java - 扩展超类时自动将子类添加到列表中
- java - JComponent setSize() 和 setLocation() 不起作用
- firebase - nodeJS中的Firebase sinon / chai单元测试
- python-3.x - Discord bot 没有发送 if not, else 语句的 else 部分?
- grafana - InfluxDB/Grafana 返回计数器从零开始
- python - 格式化包含 NaN 值的浮点数列
- sql - 如何从 SQLITE 中的 JOIN 中删除重复的列