将动作从另一个对象添加到词典时会发生什么?
首先,我试图设计一些不错的游戏内环境菜单。我的目标是动态生成每个项目。每个项目都从存储Actions的Dictionary中加载。可以从每个gameObject的最多3个组件访问字典,并附加GamePiece组件。
首先,有一个字典,其中Actions作为每个类型GamePiece的组件:
public class GamePiece : MonoBehaviour {
protected bool rightClickable = true;
protected StatManager statManager;
Transform ui;
CanvasManager canvas;
SpriteRenderer sprite;
Color spriteColor;
public Dictionary<string, Action> actions;
void Awake(){
statManager = GameObject.Find("StatPanel").GetComponent<StatManager>();
actions = new Dictionary<string, Action>();
actions.Add("Deconstruct", Deconstruct);
}
问题在于无论我如何填充字典,都会调用最后添加的字典项。所以,如果我要添加一个&#34; Destroy()&#34;打电话和&#34; SupplyPower()&#34;呼叫。这本词典只会打电话给#34;供电&#34;。这特别奇怪,因为菜单本身正在显示正确的按钮。
我怀疑问题是我在同一个gameObject上添加来自其他组件的字典项。例如,GamePiece组件保存字典并添加一些基本操作,然后Generator组件将访问添加对它自己的SupplyPower()方法的引用
public class Generator: MonoBehaviour {
public Structure structure;
void Start () {
structure = gameObject.GetComponent<Structure>();
structure.gamePiece.actions.Add("Supply Power", SupplyPower);
}
}
所以在创建上下文菜单时会发生什么:
public class ContextMenu : MonoBehaviour {
public Transform menuItem;
//Takes a ref from the calling gameObject, t. And is called from CanvasManager.cs
public void PopulateContextMenu(GameObject t)
{
Transform selections = transform.FindChild("Selections").transform; //Parent for items.
//gamePiece holds the dictionary.
GamePiece gamePiece = t.GetComponent<GamePiece>();
foreach (KeyValuePair<string, Action> kVp in gamePiece.actions)
{
GameObject menuItem =
(GameObject)Instantiate(Resources.Load("MenuItem"));
menuItem.name = kVp.Key;
menuItem.GetComponent<Text>().text = kVp.Key;
//Adding functuionality.
menuItem.GetComponent<Button>().onClick.AddListener
(() => { kVp.Value.Invoke(); });
menuItem.GetComponent<Button>().onClick.AddListener
(() => { CloseContextMenu(); });
menuItem.transform.SetParent(selections, false);
}
}
public void CloseContextMenu()
{
Destroy(this.gameObject);
}
}
从CanvasManager类调用PopulateContextMenu函数:
public class CanvasManager : MonoBehaviour {
public void ToggleContextMenu(GameObject t) {
GameObject newMenu = (GameObject)Resources.Load("ContextMenu");
newMenu = Instantiate(newMenu) as GameObject;
//Passing gameObject t into PopulatContextMenu
newMenu.GetComponent<ContextMenu>().PopulateContextMenu(t);
}
}
这里,从gameObjects OnMouseOver()回调调用ToggleContextMenu():
public class GamePiece : MonoBehaviour {
void OnMouseOver(){
if (Input.GetMouseButtonDown(1) && rightClickable) {
canvas.ToggleContextMenu(this.gameObject);
}
}
}
因此,当调用它时,它会将对自身的引用传递给CanvasManager,然后传递给ContextMenu。
答案 0 :(得分:2)
在调用之前将本地操作存储在本地,您就可以了。
在ContextMenu中:
Action newAction =kVp.Value;
menuItem.GetComponent<Button>().onClick.AddListener(() => {newAction.Invoke();});