我将C#脚本附加到场景中NPC的触发器上。基本上我只是试着让我的NPC与玩家“交谈”。如果玩家在NPC的触发器内并按下“E”键,那么NPC应该说出我的数组messages
中定义的第一条未知消息
3秒后消息消失,然后用户可以再次激活NPC,并且应该选择并返回数组中的下一条消息。
为了解决这个问题,我创建了一个bool数组messageStatus
,它保存了已告知消息的状态。
因此messages
的索引0对应于messageStatus
的索引0。
我编写了一个名为selectMessage
的函数,我传递了两个数组,然后获取状态数组的第一个索引位置,其值为false
,然后返回带有该索引的消息。然后我将该索引的状态设置为true
,因为该消息已被告知。
但是,似乎初始化(status[i] = true;
)不会更改原始数组,而只会更改参数。因为我的NPC总是告诉最后一条消息。
我想我必须将数组作为指针传递,但我不确定这是如何工作的,我的尝试到目前为止都失败了。
我该如何解决这个问题?
string selectMessage(string[] messages, bool[] status)
{
for (int i = 0; i <= status.Length-1; i++) {
if (status[i] == false) {
status[i] = true; //<-- problem
return messages[i];
}
}
return "Is everything ok?";
}
完整脚本:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TalkMalon : MonoBehaviour {
public float displayTime = 3;
public bool showMessage = false;
public string[] messages = {
"Hello, my name is Heinrich.",
"I have nothing more to say."
};
public bool[] messageStatus = {
false,
false
};
void Update()
{
if (showMessage) {
displayTime -= Time.deltaTime;
if (displayTime <= 0.0) {
showMessage = false;
displayTime = 3;
}
}
}
void OnTriggerStay()
{
if (Input.GetKeyDown(KeyCode.E)) {
showMessage = true;
}
}
void OnGUI()
{
if (showMessage) {
GUI.Label(new Rect(Screen.width / 2, Screen.height / 2, 200f+100f, 200f), selectMessage(messages, messageStatus));
}
}
string selectMessage(string[] messages, bool[] status)
{
for (int i = 0; i <= status.Length-1; i++) {
if (status[i] == false) {
status[i] = true;
return messages[i];
}
}
return "Is everything ok?";
}
}
答案 0 :(得分:3)
我真的不认为需要两个数组。在您显示的逻辑中,您将使用消息数组,以便将它们添加到集合中。所以你可以使用一个索引:
int index = 0;
string[] messages;
string GetNextMessage()
{
return (++index < messages.Length) ? messages[index] : "Is everything ok?";
}
这实际上更好的方式是您不必迭代集合来查找下一条消息。在算法中,您的解决方案是O(n),这意味着最坏的情况是集合的大小。我的解决方案是O(1),这意味着最坏的情况是一个动作。
答案 1 :(得分:1)
//第一个可能的修复
string selectMessage(string[] messages,ref bool[] status)
{
for (int i = 0; i <= status.Length-1; i++) {
if (status[i] == false) {
status[i] = true;
return messages[i];
}
}
return "Is everything ok?";
}
另一个选项,更可取的是使messageStatus数组静态。
更好的选择是实施ObservableCollection
,
但是为了你的目的,它有点开销......
//第二种可能的解决方法
public static bool[] messageStatus = {
false,
false
};
答案 2 :(得分:0)
我发现问题出在其他地方,甚至不需要使用ref
或指针将数组作为参考传递。但我很高兴你们推荐它并感谢你们非常有用的提示!
这是一个合乎逻辑的错误。我认为最后的消息总是显示,因为OnGUI是每帧执行的(afaik)?
我根据@Everts的建议改变了逻辑,这显然要好得多。我删除了根本不需要的状态数组。
修正脚本:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TalkMalon : MonoBehaviour
{
private int index = 0;
private string currentMessage = "";
private float displayTime = 3;
private bool showMessage = false;
private bool selectNextMessage = false;
public string[] messages = {
"Hello, my name is Heinrich.",
"I have nothing more to say."
};
void Update()
{
if (showMessage) {
displayTime -= Time.deltaTime;
if (displayTime <= 0.0) {
showMessage = false;
displayTime = 3;
Debug.Log(messages.Length);
if (index != messages.Length - 1) {
index++;
}
}
}
}
void OnTriggerStay()
{
if (Input.GetKeyDown(KeyCode.E)) {
showMessage = true;
}
}
void OnGUI()
{
if (showMessage) {
GUI.Label(new Rect(Screen.width / 2, Screen.height / 2, 200f, 200f), messages[index]);
}
}
}