【问题标题】:C# Delegate value does not fall within the expected range errorC# 委托值不在预期范围内错误
【发布时间】: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


【解决方案1】:

我很久以前就修复了这个问题,但如果其他人看到,问题在于委托函数使用私有作用域。从上面的问题,我的代码是:

 private delegate void Del();
 Del marySuccess = question.MarySuccess;

在第二行产生了错误。应该是:

public delegate void Del();

因为MarySuccess()方法是public方法,所以委托签名需要与之匹配,并且也是public的。实际上,由于这是在另一个类中调用该方法,因此所调用的方法必须是公共的才能工作,因此委托也需要是公共的,否则这里 marySuccess 的“值”不会“落在预期的范围内”范围'即公共代表'值'。我原以为Del() 只在这个类中使用,它可能是私有的,但不理解Del() 被用作数据类型以及变量。我觉得这是一个令人困惑的错误消息,因为我觉得委托类型被分配了一个引用而不是一个值,但如果有经验的人可以更正此分析的任何错误,那将是非常受欢迎的。

【讨论】:

    【解决方案2】:

    在一个非常相似的案例中,我遇到了同样的异常。在我的例子中,如果question 为空,表达式question.MarySuccess(获取委托)会引发这个特别意外的错误。这就是区别

    Del x = question.MarySuccess;
    

    Del x = () => question.MarySuccess();
    

    即使question 为空,第二个版本也可以工作,并且仅在稍后且仅在实际调用x 时才引发NullReferenceException

    【讨论】:

      猜你喜欢
      • 2013-10-23
      • 1970-01-01
      • 2019-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-09
      相关资源
      最近更新 更多