【问题标题】:Unity C# Shop MenuUnity C# 商店菜单
【发布时间】:2019-02-11 03:52:20
【问题描述】:

嘿伙计们,我一直在构建一个商店菜单,当按下按钮时会激活它。我在菜单中有四个按钮,对应于网格中的几个可购买项目。附加的按钮、文本和图像位于 GameObject 内。我正在尝试使用 SetActive 在菜单之间切换。我已经成功地使用 SetActive 打开和关闭菜单,但是当我尝试使用其他部分时,它们无论如何都保持不活动状态。即使按下了应该激活的按钮。我上传的图片显示了商店的层次结构。按钮位于 ShopSelection 下方,实际菜单位于 Shop 下方

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class UIManager : MonoBehaviour {

    private static UIManager instance;
    public  static UIManager Instance;
    public GameObject shopMenu, motherShips, resources, fleets, research;
    bool menuIsOpen = false;
    bool motherShipOpen = false;
    bool resourcesOpen = false;
    bool fleetOpen = false;
    public Button shop, motherShipButton, resourceButton, fleetButton, exitButton; 

    void Start () {
        shopMenu.SetActive(false);
        //Open Shop Menu
        Button btn = shop.GetComponent<Button>();
        btn.onClick.AddListener(TaskOnClick);
        //Open Motherships portion of shop
        Button btn1 = shop.GetComponent<Button>();
        btn1.onClick.AddListener(TaskOnClick3);
        //Open resources portion of shop
        Button btn2 = shop.GetComponent<Button>();
        btn2.onClick.AddListener(TaskOnClick4);
        //Open fleet portion of shop
        Button btn3 = shop.GetComponent<Button>();
        btn3.onClick.AddListener(TaskOnClick5);
        //Open Research portion of shop
        Button btn4 = shop.GetComponent<Button>();
        btn4.onClick.AddListener(TaskOnClick6);
        //Exit Menu
        Button bttn = exitButton.GetComponent<Button>();
        bttn.onClick.AddListener(TaskOnClick2);
    }

    // Update is called once per frame
    void Update () {

    }
    void TaskOnClick()
    {
        shopMenu.SetActive(true);
        menuIsOpen = true;
        motherShips.SetActive(true);
    }
    void TaskOnClick2()
    {
        if (menuIsOpen == true)
        {
            shopMenu.SetActive(false);
            menuIsOpen = false;
        }
    }
    void TaskOnClick3()
    {
        if(menuIsOpen == true)
        {
            //Open Motherships Shop
            motherShips.SetActive(true);
            resources.SetActive(false);
            fleets.SetActive(false);
        }
    }
    void TaskOnClick4()
    {
        if (menuIsOpen == true)
        {
            //Open resources Shop
            motherShips.SetActive(false);
            resources.SetActive(true);
            fleets.SetActive(false);
        }
    }
    void TaskOnClick5()
    {
        if(menuIsOpen == true)
        {
            //Open Fleet Shop
            motherShips.SetActive(false);
            resources.SetActive(false);
            fleets.SetActive(true);
        }
    }
    void TaskOnClick6()
    {
        if (menuIsOpen == true)
        {
            //Open Research Page
            motherShips.SetActive(false);
            resources.SetActive(false);
            fleets.SetActive(false);
        }
    }
}

【问题讨论】:

  • 菜单的层次结构如何?
  • @derHugo 添加了一张图片,上面有什么是什么的描述,谢谢
  • @derHugo 层次结构没有问题。如果我个人启用它们会出现的游戏对象。他们只是不使用代码激活。

标签: c# unity3d button menu


【解决方案1】:

您始终将所有回调添加到 shop 按钮,例如

Button btn2 = shop.GetComponent<Button>();
btn2.onClick.AddListener(TaskOnClick4);

不是应该的按钮motherShipButton, resourceButton, fleetButton


请注意,如果您将变量声明为Button,则不必再次调用GetComponent,它将自动引用检查器中拖放游戏对象的Button组件,因此它应该只是

shop.onClick.AddListener(TaskOnClick);

//Open Motherships portion of shop
motherShipButton.onClick.AddListener(TaskOnClick3);

//Open resources portion of shop
resourcesButton.onClick.AddListener(TaskOnClick4);

//Open fleet portion of shop
fleetButton.onClick.AddListener(TaskOnClick5);

//Open Research portion of shop
// Whatever button this belongs to
???.onClick.AddListener(TaskOnClick6);

//Exit Menu
exitButton.onClick.AddListener(TaskOnClick2);

现在也相应地命名方法,例如OpenMenuCloseMenu 等,这将使您和其他人更容易理解代码。


我也怀疑您是否需要检查 if(menuIsOpen)。由于其他游戏对象是菜单的子对象,即使调用了SetActive,它们也将保持不可见。相反,我会通过使用一种方法来确保只有一个面板处于活动状态,例如一个枚举,而不是像

enum MenuPanel
{
    MotherShips,
    Resources,
    Fleets,
    Research
}

private void ShowPanel(MenuPanel panel)
{
    // First disable all
    motherShips.SetActive(false);
    fleets.SetActive(false);
    resources.SetActive(false);

    // Than only activate according panel
    switch(panel)
    {
        case MenuPanel.MotherShips:
            motherShips.SetActive(true);
            break;

        case MenuPanel.Reaources:
            resources.SetActive(true);
            break;

        case MenuPanel.Fleets:
            fleets.SetActive(true);
            break;
    }
}

而且我仍然会为每个面板使用专用方法,例如

void Start()
{
    //...
    motherShipButton.onClick.AddListener(ShowMotherShips);
    //...
}

private void ShowMotherShips()
{
    ShowPanel(MenuPanel.MotherShips);
}

你也可以直接用 lambda 表达式来做

void Start()
{
    //...
    motherShipButton.onClick.AddListener(() => {
        ShowPanel(MenuPanel.MotherShips);
    });
    //...
}

我通常会尽量避免它,因为 1. 你不能重用这个表达式,但你可能想从其他地方调用它,以及 2. 你将无法使用 RemoveListener 最终摆脱那个调用.

【讨论】:

  • 我没有注意到我这样做了。我必须复制按钮以节省时间,并且没有将商店更改为其余按钮。我觉得我好笨。感谢您的帮助,我很感激。
猜你喜欢
  • 2017-04-30
  • 1970-01-01
  • 1970-01-01
  • 2015-02-03
  • 1970-01-01
  • 1970-01-01
  • 2016-01-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多