简体   繁体   English

如何在C#,Unity中添加Toggle的UnityEvents

[英]How to add to UnityEvents of a Toggle in C# , Unity

I am creating toggle buttons programmatic in Unity at run time, and I would like to add an event to happen to these toggles. 我在运行时在Unity中创建了程序化的切换按钮,我想在这些切换中添加一个事件。

I want to add to the Unity Event that is triggered when the toggle is clicked, but I can't seem to tie it together properly. 我想添加到单击切换时触发的Unity事件,但我似乎无法将它正确地绑在一起。

 public Toggle myToggle_Prefab;
 pulic int numberToggles;
 private Toggle[] runtimeToggles;

 private void Start()
 {
     runtimeToggles = new Toggle[numberToggles];
     for(int i = 0; i < runtimeToggles.Length; i++)
     {
          runtimeToggles[i] = Instantiate(togglePrefab);
          // ADD TO THE EVENT HERE
          runtimeToggles[i].onValueChanged.AddListener(MyMethod);
     }

 }

  private void MyMethod(int index){
       // Do something
  }

That doesn't work out because it is an integer paramater. 这没有用,因为它是一个整数参数。 The method works with a bool parameter like this: 该方法使用bool参数,如下所示:

 private void MyMethod(bool arg0)
 {
    // Do stuff
 }

But I need the integer parameter to do what I want to do. 但我需要整数参数来做我想做的事情。 Any thoughts? 有什么想法吗?

You do it like this: 你这样做:

 for(int i = 0; i < runtimeToggles.Length; i++)
 {
      runtimeToggles[i] = Instantiate(togglePrefab);
      // no-parameter version:
      runtimeToggles[i].onValueChanged.AddListener(delegate{ MyMethod(thatInteger); });
      // boolean parameter version:
      runtimeToggles[i].onValueChanged.AddListener(delegate (bool b){ MyMethod(thatInteger); });
 }

Wrap the method you want to call in a delegate (which takes either no parameters or the boolean) and call your method from there. 在委托中包含要调用的方法(不带参数或布尔值)并从那里调用方法。 Note that I've left thatInteger undefined, as your question doesn't indicate what the value is or is for. 请注意,我已经将thatInteger未定义,因为您的问题并未指出值是什么或是什么。

Do note that if you want to pass the i value, you will need to copy it to a local-scope variable (See this question for why) first: 请注意,如果要传递i值,则需要将其复制到局部范围变量(请参阅此问题,了解原因):

 for(int i = 0; i < runtimeToggles.Length; i++)
 {
      // like this:
      int thatInteger = i;
      runtimeToggles[i] = Instantiate(togglePrefab);
      // no-parameter version:
      runtimeToggles[i].onValueChanged.AddListener(delegate{ MyMethod(thatInteger); });
      // boolean parameter version:
      runtimeToggles[i].onValueChanged.AddListener(delegate (bool b){ MyMethod(thatInteger); });
 }

The boolean, by the way, I believe represents what the toggle was changed to (ie if it becomes checked, then that boolean passed is true ). 顺便说一下,我相信布尔值表示切换到了什么(即如果它被检查,那么传递的布尔值为true )。

The reason it works is because the event can invoke a narrow range of predefined delegate methods (offhand those signatures would be () , (bool state) , and (UI.Toggle t) and I'm not 100% sure about that last one) covering the most probable uses of the event. 它起作用的原因是因为事件可以调用一小部分预定义的委托方法(那些签名将是()(bool state)(UI.Toggle t)并且我不是100%肯定最后一个)涵盖事件的最可能用途。 Anything else has to get wrapped in a delegate that conforms to one of those; 任何其他东西必须包含在符合其中一个的委托中; eg delegate{ f(int i); } 例如delegate{ f(int i); } delegate{ f(int i); } , as otherwise the Unity internals don't know what it is you want to pass to your method. delegate{ f(int i); } ,否则Unity内部不知道你想要传递给你的方法是什么。

No, the official documentation doesn't list these signatures (unhelpful, that) and are invoked through internal voodoo magic (like a lot of Unity MonoBehaviour methods). 不,官方文档没有列出这些签名(无用,那些),并通过内部巫毒魔法(如许多Unity MonoBehaviour方法)调用。

I'm also new to unity and coming from other languages with Event Systems, the approach is roughly the same, just a difference in how to go about it. 我也是团结的新手,来自其他语言的Event Systems,方法大致相同,只是如何去做。

I too have an array of Toggles that I not only wanted to know when one was selected but also WHICH one dispatched the event without having to write code to iterate through array indexes or other solutions. 我也有一个Toggles数组,我不仅想知道何时选择了一个,而且还有一个调度事件而不必编写代码来迭代数组索引或其他解决方案。 My Toggles were already in the prefab, but I will be moving to Instantiating prefabs for a dynamic list. 我的Toggles已经在预制件中,但我将转向实例化预制件以获得动态列表。 Other than the the setup is the same and one can pass the toggle to the handler like so: 除了设置是相同的,可以将切换传递给处理程序,如下所示:

   private void OnEnable()
{
    _tabs = GetComponentsInChildren<Toggle>();

    // Loop through the toggles to add listeners.
    for (int i = 0; i < _tabs.Length; i++)
    {
        int idx = i;
        _tabs[idx].onValueChanged.AddListener(delegate
        {
            TabClickHandler(_tabs[idx]);
        });
    }
}

private void OnDisable()
{
    // Loop through toggles to remove listeners...
    for (int i = 0; i < _tabs.Length; i++)
    {
        // As mentioned above, you need a local variable to pass to the delegate.
        int idx = i;
        _tabs[idx].onValueChanged.RemoveListener(delegate
        {
            TabClickHandler(_tabs[idx]);
        });
    }
}

public void TabClickHandler(Toggle tab)
{
    // State changes are handled here which includes the previous toggle being set to off.  Therefore, filter for only the isOn == true state changes
    if (tab.isOn)
        Debug.Log("Tab: " + tab.name + "  isOn State:" + tab.isOn);
    // Do any stuff you want here.  You now can identify the tab. In my case it was to start the load process for a different inventory classification list.
}

Just make sure to remove your listeners to avoid memory leaks. 只需确保删除侦听器以避免内存泄漏。 If you are familiar with event systems, a lot of other languages also require this. 如果您熟悉事件系统,许多其他语言也需要这样做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM