这是一个在Unity游戏引擎中编程C#的问题,但它可能是没有Unity经验的C#委托专家可以知道我做错了什么? (我确实已经在Unity论坛上发帖了。)
我试图传递一个在固定函数内调用的任意函数,它本身是通过AddListener
事件的InputField.onEndEdit
函数使用delegate关键字调用的。我是代表们的新手,但据我所知,我需要创建一个新的代表才能做到这一点,并且在阅读了一些仍然卡住的代表文章后,我有点纠结。目前,代码编译但出现ArgumentException
错误。不幸的是,在Unity Editor中使用完整堆栈跟踪时,这就是我得到的所有堆栈跟踪:
ArgumentException: Value does not fall within the expected range.
CharacterController3D..ctor () (at Assets/Entities/DungeonCell/Priest/CharacterController3D.cs:95)
脚本名称为CharacterController3D.cs
。此类中的第95行构造函数生成此错误:
Del marySuccess = question.MarySuccess;
结束目标:当玩家输入玩家在游戏中触发任意问题的答案时,ProcessAnswer函数将调用定制函数处理每个问题的正确答案,即每个问题将具有处理正确答案的不同函数响应。同样,如果玩家给出错误的答案等,ProcessAnswer函数将为该问题调用不同的自定义函数。
下面是ProcessAnswer函数,其中传递了任意委托delegate1
,当给出正确答案时,在以下代码块中运行:
private void ProcessAnswer (InputField input, string answer, float clockStart, Del delegate1)
{
if (String.Equals(answer, input.text.Trim(), StringComparison.OrdinalIgnoreCase)) // trim trailing spaces, accept any case in letters typed
{
countdownTimer.enabled = false; // stops timer
float timePoints = Mathf.Round(2000/(clockStart - countdownTimer.TimeStoppedTenthsSecond()));
delegate1();
}
else ....
上面的函数在同一个脚本中被调用:
string answer = "grace";
clockStart = 90f;
inputField.onEndEdit.AddListener(delegate { ProcessAnswer(inputField, answer, clockStart, marySuccess); });
其中marySuccess
是本例中的委托参数,由:
private delegate void Del();
Del marySuccess = question.MarySuccess;
仍然在同一个脚本中,question
这里被声明为同一对象上单独组件脚本的静态实例。我知道必须让代表静态参考它,无论如何都不能以非静态方式工作:
private static Questions question;
并在Awake方法中初始化,所有脚本都在同一个脚本中:
question = this.GetComponent<Questions>();
修改 作为评论,道歉错过了MarySuccess()方法代码本身,它与委托声明具有相同的签名(没有参数,返回void):
public void MarySuccess()
{
string phrase1 = "a";
string phrase2 = "b";
string phrase3 = "c";
string phrase4 = "d";
thoughtText.color = new Color(0.55f, 0f, 0.03f); // now matches (141,0,8) colour of input text, was Color.red;
thoughtText.fontSize = 22;
StartCoroutine(player.FillThoughtBox(phrase1, 3, phrase2, 3, phrase3, 5, phrase4));
playerInputPanel.SetActive(false);
player.Invoke("MaryHailed", 10f);
Invoke("HideThoughtPanel", 22f);
}
// use Invoke() with desired delay, so that player can start moving and have more time to read the words before it disappears
private void HideThoughtPanel()
{
thoughtButtonPanel.SetActive(false);
}
EDIT2
我检查过public void MarySuccess () {}
为空,仍然会出现相同的异常错误。
任何建议都非常感谢,谢谢!
答案 0 :(得分:0)
我很久以前已经解决了这个问题,但是如果其他人阅读了,问题出在使用私有作用域作为委托函数。从上面的问题来看,我的代码是:
private delegate void Del();
Del marySuccess = question.MarySuccess;
在第二行产生了错误。应该是:
public delegate void Del();
因为MarySuccess()
方法是公共方法,所以委托签名需要匹配它,并且也是公共的。实际上,由于这是在另一个类中调用方法,因此调用的方法必须是公共的才能工作,因此委托也必须是公共的,否则此处marySuccess
的“值”不会“落入”预期范围”,即公共代表的“值”。我以为,由于Del()
仅在此类中使用,因此它可以是私有的,但不知道将Del()
用作数据类型和变量。我感到这是一个令人困惑的错误消息,因为我感觉正在为该委托类型分配一个引用而不是值,但是如果有经验的人可以在此分析中更正任何错误,则非常欢迎。
答案 1 :(得分:0)
在非常相似的情况下,我也遇到了同样的例外。以我为例,如果question.MarySuccess
为null,则表达式question
(获取委托)会引发此特别意外的错误。那是之间的区别
Del x = question.MarySuccess;
和
Del x = () => question.MarySuccess();
即使question
为空,第二个版本也可以工作,并且仅在以后调用NullReferenceException
并且仅在实际调用x
时才引发{{1}}。