2016-03-31 19 views
3

Başka bir nesneden bir sözlüğe bir Eylem eklediğinizde ne olur?Unity3D Oyun İçi Bağlam Menüler - Garip davranış

İlk olarak, bazı iyi oyun içi içerik menüleri tasarlamaya çalışıyorum. Amacım her bir öğeyi dinamik olarak oluşturmaktır. Her öğe, Eylemleri saklayan bir Sözlük'den yüklenir. Sözlüğe, bir GamePiece bileşeninin eklendiği her gameObject öğesinin 3 bileşeninden erişilir.

Birincisi, her tür GamePiece bir bileşeni olarak yaşayan Eylemler ile bir sözlük vardır:

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); 
    } 

Sorun sözlüğü doldurmak nasıl olursa olsun, son eklenen Sözlük öğesi denir olmasıdır. Yani bir "Destroy()" çağrısı ve bir "SupplyPower()" çağrısı ekleyecek olsaydım. Sözlük sadece “Supply Power” olarak adlandırılacaktır. Bu özellikle garip çünkü menüler doğru düğmeleri gösteriyor.

ben de aynı GameObject diğer bileşenlerden Sözlük öğeleri ekleyerek ediyorum olmak sorunu şüpheli. Örneğin, GamePiece bileşeni() metodu sözlüğünü tutan ve bazı temel işlemleri ekler ve sonra Jeneratör bileşeni olduğunu erişmek bir o kendi SupplyPower bir başvuru katacak

public class Generator: MonoBehaviour { 

    public Structure structure; 

    void Start() { 
     structure = gameObject.GetComponent<Structure>(); 
     structure.gamePiece.actions.Add("Supply Power", SupplyPower); 
    } 
} 

Yani burada bağlam menüsü ne olur oluşturuldu:

PopulateContextMenu işlevi CanvasManager sınıfından denir
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); 
    } 
} 

: Burada

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() denir gameObjects OnMouseOver() callback'inde den: Bunun adı Yani

public class GamePiece : MonoBehaviour { 

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

, bu CanvasManager için kendisine bir başvuru ileten ve sonra ContextMenu kapalı teslim alma.

cevap

1

İşlemleri çağırmadan önce yerel olarak depolayın ve gitmek için iyi bir konum. ContextMenu olarak

: bu kadar

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

. Teşekkürler! – Don