【问题标题】:Unity3D In-Game Context Menus - Strange behaviourUnity3D 游戏内上下文菜单 - 奇怪的行为
【发布时间】:2016-07-20 04:57:21
【问题描述】:

当您从另一个对象向字典添加操作时会发生什么?

首先,我正在尝试设计一些不错的游戏内上下文菜单。我的目标是动态生成每个项目。每个项目都是从存储动作的字典中加载的。每个游戏对象的最多 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);
    }

问题是无论我如何填充字典,最后添加的字典项都会被调用。因此,如果我要添加一个“Destroy()”调用和一个“SupplyPower()”调用。字典只会叫“电源”。这特别奇怪,因为菜单本身显示的是正确的按钮。

我怀疑问题是我在同一个游戏对象上添加了来自其他组件的字典项。例如,GamePiece 组件保存字典并添加一些基本操作,然后生成器组件将访问它并添加对其自己的 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);
    }

}

这里,ToggleContextMenu() 是从 gameObjects OnMouseOver() 回调中调用的:

public class GamePiece : MonoBehaviour {

    void OnMouseOver(){
        if (Input.GetMouseButtonDown(1) && rightClickable) {
            canvas.ToggleContextMenu(this.gameObject);
        }
    }
}

因此,当它被调用时,它会将对自身的引用传递给 CanvasManager,然后将其移交给 ContextMenu。

【问题讨论】:

    标签: unity3d


    【解决方案1】:

    在调用之前将操作存储在本地,一切顺利。

    在上下文菜单中:

    Action newAction =kVp.Value;
    menuItem.GetComponent<Button>().onClick.AddListener(() => {newAction.Invoke();});
    

    【讨论】:

    • 就是这样。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多