【发布时间】:2018-05-24 11:20:21
【问题描述】:
这是一个在 Unity 游戏引擎中编程 C# 的问题,但可能是没有 Unity 经验的 C# 代表专家知道我在做什么错吗? (我已经在 Unity 论坛上发过帖子了)。
我正在尝试传递要在固定函数内调用的任意函数,该函数本身是通过 InputField.onEndEdit 事件的 AddListener 函数使用委托关键字调用的。我是代表的新手,但据我所知,我需要创建一个新的代表来执行此操作,而且我有点纠结,阅读了一些仍然卡住的代表文章。目前,代码编译但得到ArgumentException 错误。不幸的是,在 Unity 编辑器中打开了完整的堆栈跟踪,这就是我得到的所有堆栈跟踪:
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>();
编辑 作为 cmets,对于缺少 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 () {} 为空,仍然给出相同的异常错误。
任何建议非常感谢,谢谢!
【问题讨论】:
-
ctor只是构造函数的简写。关于您的 ArgumentException,请查看其堆栈跟踪。它告诉您导致异常的方法调用顺序。Del marySuccess = question.MarySuccess;可能仅在question.MarySuccess是一个其 getter 具有副作用的属性时才导致 ArgumentException(即,以某种形式或形状,它直接或间接地做的不仅仅是简单地返回属性值) -
感谢@elgonzo、@dymanoid、@SaturnusK1,现在已经包含了
MarySuccess()方法的完整代码,但堆栈跟踪不是很有帮助。我不太了解副作用,在这个委托案例中不清楚 getter 指的是什么。 -
谢谢@dymanoid,第95行构造函数是
Del marySuccess = question.MarySuccess;,正如问题顶部所提到的,应该在编辑时更清楚,顶部的所有代码都来自这个CharacterController3D类。我尝试删除 MarySuccess() 方法中的所有代码,即public void MarySuccess() {},但仍然给出相同的异常错误。然后,我尝试将 Questions 类更改为从 ScriptableObject 继承而不是 Unity Monobehaviour 类,以其他方式破坏它,但此构造函数仍然存在错误,同一行。将尝试更多打印到控制台和这些工具,谢谢。
标签: c# unity3d input delegates event-handling