Monogame游戏设置

Monogame game settings

我正在使用 C# 和 monogame 开发一个平台游戏,作为一个有趣的项目来提高我的技能。我想添加对音频、视频、控件等设置的支持,但我不知道这样做的最佳方式。

我计划有一个 XML 文件来存储所有设置,如下所示:

<Settings>
  <Audio>
    <masterVolume>100</masterVolume>
    <musicVolume>40</musicVolume>
    <sfxVolume>90</sfxVolume>
  </Audio>
  <Video>
    <Resolution>
      <width>1920</width>
      <height>1080</height>
    </Resolution>
  </Video>
  <Controls>
    <forward>W</forward>
    <back>S</back>
    <left>A</left>
    <right>D</right>
  </Controls>
</Settings>

我的计划是使用设置 class,其中包含音频、视频和控件等的静态变量,这些变量分为单独的 classes,以便我可以通过 [=23= 访问它们]Settings.Audio.MasterVolume或Settings.Controls.Forward。 我想使用 Linq 从 XML 将设置加载到这些 classes 中,并且我想在用户更改设置时将它们保存到 XML 文件中。

我知道也可以使用单例,但据我所做的研究表明,它有太多缺点。是真的吗?

这是执行此操作的好方法还是有更好的方法允许我在整个项目中访问设置而无需所有内容都是静态的?

提前致谢!

在我的游戏项目中,我总是使用一些静态 类(and/or 变量)来保存在整个游戏中有效的信息。 如果您希望能够从游戏的不同点更改音量等,这可能会派上用场,尤其是对于音频设置。 这不一定只包括用户设置。考虑在某些角色说话时降低背景音乐。

长话短说: 我会选择静态方法。但注意不要超过它。

你的方法行得通。但是,您限制 class.

的重复使用

如果你向别人描述MyClass,你会说用来读取配置参数的方法对MyClass来说是必不可少的吗?换句话说:如果配置参数不是从配置文件中读取的,而是从 CSV 文件、互联网或其他任何方法读取的,那么你的 class 的大部分代码会毫无意义吗?

您可能会说不:如果以不同方式提供配置参数,我的 class 的大部分代码都可以重用。

那么,为什么要将您的 class 限制为只有从配置文件读取配置参数才能工作的 class?

我猜你现在有这样的东西:

static class ConfigurationSettings
{
    public static int LeftControl => ...
    public static int RighControl => ...
}

class MyClass
{
    // MyClass uses configuration settings:
    public int LeftControl => ConfigurationSettings.LeftControl;
    public int RightControl => ConfigurationSettings.RightControl;

    ...
}

您不能实例化 MyClass 的两个对象,每个对象都有自己的一组配置参数。您不能创建使用不同方法提供配置值的 MyClass 对象。

我经常需要的一个用例是单元测试:我想要一种快速的方法来更改配置设置,而不必更改单元测试项目的配置文件。

允许 class 的用户提供不同的设置方法的一种简单方法是创建一个带有设置的接口,并提供一个带有此接口的构造函数:

interface IMySettings
{
    int LeftControl {get;}
    int RightControl {get;}
    ...
}

class ConfigurationSettings : IMySettings
{
     // ConfigurationSettings reads settings from the configuration file
}

class MyClass
{
    // default constructor use the configuration file via ConfigurationSettings:
    public MyClass() : this (new ConfigurationSettings())
    {
    }

    // extra constructor for those who don't want to use configuration file
    public MyClass(IMySettings settings)
    {
        this.Settings = settings;
    }

    protected readonly IMySettings settings;

    // MyClass uses settings:
    public int LeftControl => this.settings.LeftControl;
    public int RightControl => this.settings.RightControl;
}

想要使用配置文件中的设置的用户可以使用默认构造函数;需要特定设置的用户使用替代构造函数。如果您想要两个不同的 MyClass 对象,每个对象都有自己的设置,也可以使用此替代构造函数。

乍一看,似乎只要稍作改动,您仍然可以使用配置文件。但是,为了能够实现接口,读取配置文件(MyClass)的class不能是静态的。

然而,你是对的:只有一个配置文件,因此应该只有一个 class 从配置文件读取的实例:创建一个单例。

根据我的经验,代表配置的 classes 是使用单例而不是静态的常用原因之一 class