我正在使用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>
我的计划是使用一个设置类,该类具有用于音频,视频和控件等的静态变量,这些变量被划分为单独的类,以便我可以通过 Settings.Audio.MasterVolume 或 Settings.Controls.Forward 。 我想使用Linq将设置从XML加载到这些类中,并且当用户更改设置时将设置保存到XML文件中。
我知道也可以使用单例,但是据我从研究中可以看出,这样做有很多缺点。是真的吗?
这是执行此操作的一种好方法吗?还是有一种更好的方法可以使我在整个项目中访问设置而又没有使所有内容保持静态?
谢谢!
答案 0 :(得分:1)
在我的游戏项目中,我总是使用一些静态类(和/或变量)来保存整个游戏中有效的信息。 如果您希望能够从游戏的不同角度更改音量等,这对于音频设置尤其有用。 这不一定只包括用户设置。 Thinkig降低某些角色说话时的背景音乐。
长话短说: 我会选择静态方法。但是请注意不要超过它。答案 1 :(得分:1)
您的方法有效。但是,您限制了班级的重用。
如果您要向他人描述MyClass
,您是否会说用于读取配置参数的方法对于MyClass
是必不可少的?换句话说:如果不是从配置文件中读取配置参数,而是从CSV文件,互联网或其他方法中读取配置参数,则该类的大多数代码会变得毫无意义吗?
您可能会拒绝:如果以不同方式提供配置参数,则可以重用我班上的大多数代码。
那么为什么将您的类限制为只能从配置文件中读取配置参数的类呢?
我猜您当前有类似的东西:
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
对象。
我经常需要的一种用例是在单元测试时:我想要一种快速的方法,能够在无需更改单元测试项目的配置文件的情况下更改配置设置。
允许您的类的用户提供不同的设置方法的简单方法是使用设置创建一个接口,并为该构造函数提供该接口:
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
)的类不能是静态的。
但是,您是对的:只有一个配置文件,因此应该只有一个从配置文件读取的类实例:创建一个单例。
根据我的经验,代表配置的类是使用单例而不是静态类的常见原因之一