我已经创建了一堆静态功能,以帮助我在需要时设置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;
}