(UNITY)创建一个按钮,为其提供委托(或操作),并给该委托参考参数



我已经创建了一堆静态功能,以帮助我在需要时设置UI元素,例如初始化build-units菜单或资源图(这是用于策略)游戏)。我一直在使用代表和操作,以使我可以将按钮初始机递给函数,以订阅按钮的OnClick事件。到目前为止,这一切都很好。

但是,当我有一个可以更改其文本值的文本字段时(例如,播放器要购买多少个项目的输入号),代表不会参考。因此,如果我打开菜单,则菜单的输入字段为0.0,并调用函数购买(0.0F)。但是,如果我将输入字段中的值更改为3.0,则按钮仍然调用购买(0.0F),因为这是创建值时的值。

奇怪的是,直到最近我才遇到这个问题。请参阅,我的普通按钮带有输入字段的预制带有一个按钮,并且一个输入字段是该按钮。据我所知,这意味着该按钮可以将字段的文本作为参考处理,因为它始终知道输入字段在哪里。这是创建fieldbutton的功能:

 // Function to quickly set up a numeric field button.
 // This accomodates a function with a single float parameter.
 public delegate void floatDel(float f);
 public static GameObject InitFieldButton(Transform parent, Vector3 position, string text, floatDel function)
 {
     GameObject newElement = GameObject.Instantiate(fieldButton);
     // Establish UI transform data.
     newElement.transform.SetParent(parent);
     newElement.transform.localPosition = position;
     newElement.transform.GetChild(0).GetComponent<Text>().text = text;
     // Assign the argued function to the button, with the input text as a parameter to that function.
     newElement.GetComponent<Button>().onClick.AddListener(delegate { function(float.Parse(newElement.GetComponentInChildren<InputField>().text)); });
     return newElement;
 }

这有效。如果我更改输入字段中的值,则按钮将带有更新值的函数。

,但我还使用了一堆参考一个输入字段的按钮,因为当我想让玩家购买很多不同的东西时,只需要指定一个数量即可。显然,这是两个预制:一个按钮和一个输入场。因此,我的initbutton()函数正在做同样的事情:

此超载可容纳一个具有两个参数的函数:交易良好,要交易的数量。

 public delegate void purchaseDel(Good g, float f);
 public static GameObject InitButton(Transform parent, Vector3 position, string text, purchaseDel function, Good good, GameObject inputField)
 {
     GameObject newElement = GameObject.Instantiate(button);
     // Establish UI transform data.
     newElement.transform.SetParent(parent);
     newElement.transform.localPosition = position;
     newElement.GetComponentInChildren<Text>().text = text;
     // Assign the function delegated to this button.
     newElement.GetComponent<Button>().onClick.AddListener(delegate { function(good, float.Parse(inputField.GetComponent<InputField>().text)); });
     return newElement;
 }

我尝试了很多事情。使用" REF"似乎不是一个选项,因为匿名功能(例如我要交给OnClick的功能)无法接受参考。我目前正在考虑给按钮一个自定义脚本来存储我需要的所有数据,但我希望这会凌乱且非常非生成。

这似乎是一件很普遍的事情。有更好的方法吗?

自己解决了。原来我很愚蠢。

问题实际上是菜单类别以及如何用按钮填充自己。

 // Create a buy button for every type of good that can be bought.
 for (int g = 0; g < SGoods.Instance.goodsList.Count - 1; g++)
         {
             // Get the text input for how much the player wants to buy.
             GameObject buyQuantity = MenuElements.InitField(transform,
                 new Vector3(205.0f, -40.0f));
             // Call the Button initialiser.
             GameObject buyButton = MenuElements.TestInitButton(transform,
                 new Vector3(205.0f, -60.0f - 30.0f * g),
                 "Buy",
                 market.BuyFrom,
                 SGoods.Instance.goodsList[g],
                 buyQuantity.GetComponent<InputField>());
         }

我将for循环中的买入输入字段放置在for循环内,即使我只想创建其中一个。然后,我只是用循环的每个环路覆盖它。因此,所有按钮都忽略了输入字段的更改,除了最后一个按钮...

奇怪的是,在重新完成此代码之后,我现在会出现一个错误警告我。我很确定这就是我以前的使用方式,而且没有错误。

无论如何,我想一旦Unity在某个地方有一个对象的引用,它就可以将其作为参考类型。我刚刚宣布该引用循环外:

 GameObject buyQuantity = MenuElements.InitField(transform,
             new Vector3(205.0f, -40.0f));
 for (int g = 0; g < SGoods.Instance.goodsList.Count - 1; g++)
 {
     // Call the Button initialiser.
     GameObject buyButton = MenuElements.TestInitButton(transform,
         new Vector3(205.0f, -60.0f - 30.0f * g),
         "Buy",
         market.BuyFrom,
         SGoods.Instance.goodsList[g],
         buyQuantity.GetComponent<InputField>());
 }

最终这不需要任何花哨的东西。没有参考关键字,没有疯狂的lambda功能。只是定期的匿名代表工作正常。菜单类持有的输入场似乎就足够了。

public static GameObject TestInitButton(Transform parent, Vector3 position, string text, purchaseDel function, Good good, InputField inputField)
 {
     GameObject newElement = GameObject.Instantiate(button);
     newElement.transform.SetParent(parent);
     newElement.transform.localPosition = position;
     newElement.GetComponentInChildren<Text>().text = text;
     // Assign the function delegated to this button.
     newElement.GetComponent<Button>().onClick.AddListener(() => function.Invoke(good, float.Parse(inputField.text)));
     return newElement;
 }

最新更新