C# - 更改函数内的数组值
Posted
技术标签:
【中文标题】C# - 更改函数内的数组值【英文标题】:C# - Change array values inside a function 【发布时间】:2017-10-22 13:38:11 【问题描述】:我将 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?";
【问题讨论】:
使用C#的ref
参数支持。
与您的问题略微无关,但为什么不创建一个小类,其中包含描述是否被告知的消息和布尔值。然后你有这些而不是 2 个集合?
使用上面 Dave 的建议或使用KeyValuePair
。
这里到底有什么问题?
谢谢你的提示,我真的很感激他们 :) 问题是我的 NPC 总是告诉最后一条消息
【参考方案1】:
我真的不认为需要两个数组。在您展示的逻辑中,您使用消息数组按顺序将它们添加到集合中。所以你可以只使用一个索引:
int index = 0;
string[] messages;
string GetNextMessage()
return (++index < messages.Length) ? messages[index] : "Is everything ok?";
这实际上更好,因为您不必迭代集合来查找下一条消息。在算法中,您的解决方案是 O(n),这意味着最坏的情况是集合的大小。我的解决方案是 O(1),这意味着最坏的情况是一个动作。
【讨论】:
【参考方案2】://第一个可能的修复
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
;
【讨论】:
这里为什么需要 ref?他影响的是数组的内容而不是数组引用。为什么推荐静态?也不需要。【参考方案3】:我发现问题出在其他地方,甚至没有必要使用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]);
【讨论】:
您将遇到一些超出范围的异常。在 OnTriggerStay 中,showMessage = (index 我不确定您指的是什么?在 OnTriggerStay 中没有像showMessage = (index < messages.Length);
这样的代码。我测试了代码,没有任何期望。
如果你一直去NPC,按E,因为索引永远不会设置回0,它会一直增加。您需要防止索引高于消息。长度。如果索引太大,我给出的行会阻止你运行代码。
@Everts,我已经用 if (index != messages.Length - 1)
行阻止它以上是关于C# - 更改函数内的数组值的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Mongoose 中更改文档子数组的对象内的布尔值?