unity3d Unity c#:代码结构或如何从另一个类/脚本访问方法/变量?

q9yhzks0  于 2022-11-16  发布在  C#
关注(0)|答案(1)|浏览(197)

我有两门课:Menu_Buttons,其中定义了单击菜单中不同按钮时执行的方法;PauseMenu,定义了在游戏过程中按下菜单键时会发生的情况。
菜单按钮(_B):

public class Menu_Buttons : MonoBehaviour
{
    public void Menu_NewGameClick()
    {
        SceneManager.LoadScene(1);
    }
    
    public void Menu_ContinueClick()
    {
        Debug.Log("This will continue the game from the last save");
    }

    public void Menu_LoadGameClick()
    {
        SceneManager.LoadScene(1);
        Debug.Log("Another menu will show to choose which save to load");
    }

    public void Menu_SaveGameClick()
    {
        SaveItem();
        Debug.Log("This will save the game");
    }

    public void Menu_OptionsClick()
    {
        Debug.Log("This will show the game options");
    }

    public void Menu_QuitClick()
    {
        Application.Quit();
        Debug.Log("The Game should quit now");
    }
}

暂停菜单:

public class PauseMenu : MonoBehaviour
{
    //private bool isPauseMenuOpened = false;
    public GameObject pauseMenu;
    

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.B))
        {
            if (pauseMenu.activeSelf)   { ClosePauseMenu(); }
            else                        { OpenPauseMenu(); }
        }
    }

    public void OpenPauseMenu()
    {
        pauseMenu.SetActive(true);
        Cursor.visible = true;
        Cursor.lockState = CursorLockMode.Confined;
        //isPauseMenuOpened = true;
        Time.timeScale = 0f;
    }

    public void ClosePauseMenu()
    {
        pauseMenu.SetActive(false);
        Cursor.visible = false;
        Cursor.lockState = CursorLockMode.Locked;
        //isPauseMenuOpened = false;
        Time.timeScale = 1f;
    }
}

我想添加另一个名为Menu_ResumeClick的方法,它可以从暂停菜单继续游戏。当然,我可以在PauseMenu脚本中创建这个方法,然后一切就都好了。它看起来像这样:

public void Menu_ResumeClick()
    {
        ClosePauseMenu();
    }

但是,由于我希望保持有序,我认为最好将此方法与所有其他类似方法沿着放在Menu_Buttons脚本中。因此,我尝试了以下方法:

public void Menu_ResumeClick()
    {
        PauseMenu.ClosePauseMenu();
    }

然后问题就开始了......我得到一个错误:非静态字段方法或属性需要一个对象引用。如果我将这些类中的任何一个更改为静态,我会收到错误消息:我不能在静态类中声明示例成员。更不用说静态类不能从MonoBehaviour继承。也许我能以某种方式解决这些问题,但问题是我不想仅仅因为我宁愿在另一个类中有一个方法而改变整个代码。这只是为了保持事情的组织性,仅此而已。
我不得不承认,我对这些东西的工作方式有点失望。我可以很容易地把Menu_ResumeClick()方法在PauseMenu类中,但是将来如果我在不同的脚本中分散了各种方法,可能很难跟踪这些内容。最合理的解决方案是将每个菜单按钮放在Menu_Buttons类中,然后从那里访问它们,但它也带来了我所描述的问题。实际上,这不是我第一次遇到从其他类访问方法或变量的问题--似乎总是会有一些困难。看起来编写代码的最佳方式是为整个游戏只编写一个类,因为这样我就可以轻松地访问任何东西--但问题还是出在如何把事情安排得井井有条上。

**因此,问题是:**我能轻松地使用其他类的方法(或变量),而无需为此目的更改整个代码吗?换句话说,我能以某种方式调用另一个类的方法吗?className.MethodName();或从另一个类设置变量,如下所示:className.varName = 2;,而不使所有内容都是静态的,等等。**还有一个额外的问题:**如果这是不可能的,那么我应该如何构造我的代码?我应该尝试将尽可能多的内容压缩到一个类中以便能够轻松地访问它们吗?我应该使类成为静态的吗?只要可能,等等?

mrwjdhj3

mrwjdhj31#

PauseMenu中,您可以为Menu_Buttons添加一个字段,Unity可以对其进行序列化,这样您就可以在检查器中提取GameObject(包含Menu_Buttons的字段),并且可以从PauseMenu调用其公共方法(并访问其公共成员)。

public Menu_Buttons MenuButtons;

// or (I much more like this version, keeping things as encapsulated as possible)
[SerializeField] private Menu_Buttons _menuButtons;

private void Resume() => _menuButtons.Menu_ResumeClick();

根据注解编辑:
这两个脚本可以相互引用。由于这两个脚本在逻辑上是相关的,所以我不会将它们分开,因为无论如何,通过引用,我们将它们耦合在一起。
示例:

public class Menu_Buttons : MonoBehaviour
{
    [SerializeField] private PauseMenu _pauseMenu;

    public void Menu_ResumeClick() => _pauseMenu.ClosePauseMenu();

    // ...
}

public class PauseMenu : MonoBehaviour
{
    [SerializeField] private Menu_Buttons _menuButtons;

    // ...

    public void ClosePauseMenu()
    {
        // ...
    }
}

相关问题