游戏邦在:
杂志专栏:
gamerboom.com订阅到鲜果订阅到抓虾google reader订阅到有道订阅到QQ邮箱订阅到帮看

解析游戏设置与引擎代码的分离问题

发布时间:2011-12-13 15:09:04 Tags:,,

作者:Alistair Doulin

我曾经使用三种不同的游戏引擎,并且它们的游戏设置和引擎都与源代码紧扣在一起。在Unity中,所有的游戏物体都源于MonoBehaviour,并受益于Unity的强大功能。但是,最近我不再使用这种方法了,而是更加关注于“分离问题”。也就是主张完全分离游戏设置,保持游戏引擎的独立性。并且事实也证明了这个方法的可用性,我将在此讨论这种分离游戏设置的方法以及它值得推荐的原因。

Separation Of Gameplay(fromdoolwind.com)

Separation Of Gameplay(fromdoolwind.com)

为什么要将游戏玩法与游戏的其它部分分离开来?以下有几点原因:

虽然不同游戏间也有很多相同之处,如渲染,视频,动画及输入装置等系统上的共同点,但其游戏代码却各不相同。(游戏邦注:例如《战地风云3》与《NFS: The Run》虽然拥有相同的游戏引擎,但游戏玩法大不相同)。

游戏设置代码的所有权与游戏中的其它系统有所不同。大多数游戏开发团队中都有游戏设置和引擎开发两个小团队。而这两块领域要求的技能也不相同,这也是为何要特别区分它们的原因。但是这两个团队的规模通常都是一样大小。

设计者只需要接触游戏设置的相关内容,而不用涉及着色器或任何特殊的输入代码。分离这些代码能够简化设计者的工作,也有利于保护他们的工作内容和游戏引擎。

允许针对于游戏代码的单元测试。而因为这是关于游戏设置的测试组,所以更容易执行与维护。

游戏开发中最困难也是最重要的部分便是“寻找乐趣”。通过分离游戏设置,开发者可以着重关注特定的任务而无需担心其它引擎的相关问题。需要处理的代码越少,开发者越能够以更高的效率开发出最好的游戏。

如何做?

我们在游戏开发中使用Unity和C#,并且将游戏设置进行分离,归于它自己单独的一个程序库(特别是.dl)。这个程序库与Unity无关,并不从属于任何特定的引擎。理论上来讲,我们可以用XNA或者其它能够与.NET程序库相交流的引擎替换Unity。

游戏引擎便包含了这种程序库,并利用这种程序库去模拟游戏世界。在Unity中,这么做就与将.dll拖放到游戏中并因此快速利用各种公共类一样简单。有一种选择便是通过界面让游戏引擎上的所有内容访问程序库。这么做能够让你更好地完全区分游戏引擎与游戏设置。我在开发第一款游戏的时候使用了这种方法,建议那些大型游戏开发者或团队以使用这种通过界面进行所有系统交流的方法。

我曾经在使用XNA开发一款游戏的时候发现了这一技巧,认为这是一个非常简单的操作过程。你只需要将参考数据添加到游戏设置.dll中便可以围绕它进行编码。

脚本语言

这种分离工作需要借助脚本语言的帮助。通过Lua等脚本语言,游戏设计者可以更好地掌握游戏中的某些行为。我在很多游戏中都利用了脚本语言的功能,并且也发现它能够很好地辅助分离工作。

游戏设置的分离是常规脚本语言分离的一种延伸,它打破了传统脚本语言范例。我们不是向设计师和游戏设置程序员展示一些引擎功能,让他们据此创造游戏世界,而是由设计师和程序员先创造好游戏世界,再让引擎开发者使用这个世界。如此分工让他们能够更有效地进行游戏开发的基础工作。因此这两者都很清楚自己必须实现的游戏功能,而且能够通过一个简单且明确的界面进行交流。设计者可以专注于于执行有趣的游戏设置,而引擎编码员则能够与美工展开合作,致力创造游戏外观和风格的艺术效果。

如Unity和Unreal等引擎的所有游戏设置代码已有专属的脚本语言。然而我认为我们还可以更进一步发展,甚至在这种脚本语言中创造一个关于独立于任何特定引擎代码的程序库。在我们的游戏中有三个主要域:

1.游戏设置绝对代码(如Player ship和Torpedo)

2.针对该游戏的引擎代码(如输入原始代码,并以一个适当的形式形成特定的游戏设置代码或着色器)

3.引擎代码(对Unity和Unreal来说,也就是我们很少访问的C++代码)

负面因素

关于这种方法我也意识到了一些负面因素。关于游戏引擎和游戏设置紧密结合在一起的游戏中会出现许多重复数据。而当游戏设置代码未能意识到引擎数据的结构时,它就会再次复制出相同的游戏设置代码。如此,数据结构转变只会不断地增加内存的占有量。

另外一个负面因素便是,游戏引擎的一些有益功能并不能为游戏设置所用。Unity的两大重要功能是触发作用和协同功能。但是当游戏设置要使用这些功能时,就必须再次进行代码复制。

两个世界

关于游戏世界有两个例子,游戏设置具体实例和引擎/渲染具体实例。关于复杂的游戏,这种分离方法能够帮助引擎开发者按照自己的最佳数据结构去保存游戏世界。这种分离方法同样也能够简化游戏引擎的多重执行过程。

单元测试

单元测试是游戏设置分离的最大优点之一。你可以简单地对游戏设置进行单元测试,然后再有针对性地执行后续测试,以此确保游戏设置的“准确性”。当单元测试只针对于游戏设置时,便能够更加快捷地获得较高的代码覆盖率。我希望在不久的未来我们能够将游戏设计文档转变成一些具体的游戏设置单元测试。游戏设置团队拥有游戏设置代码以及测试套件的所有权。

未来计划

今后,我计划开始尝试之前未曾触及的领域。首先便是尝试着解决游戏设置和游戏引擎之间的重复数据问题。我认为,解决这个问题便需要在游戏设置中安插关于游戏引擎数据结构的相关参考内容。就像在Unity3D中包含有UnityEngine.dll一样。空间数据结构(如Vector3,Quaternion等)便能够直接用于游戏设置中。这些数据虽然破坏了游戏设置和游戏引擎之间的抽象概念,但是如果能够合理使用,还是能够增加更多价值。(本文为游戏邦/gamerboom.com编译,拒绝任何不保留版权的转载,如需转载请联系:游戏邦

Separation Of Gameplay

by Alistair Doulin

I’ve worked on three different game engines and all have had gameplay and engine intertwined throughout the source code. In Unity, all game objects inherit from MonoBehaviour giving them full access to the power of Unity (and forming a hard link between game and engine). Recently, I’ve moved away from this approach to a better “separation of concerns”. I completely separate out the gameplay making it engine agnostic. This has worked well and I plan to use this approach for most of the games I create in the future. Today I discuss this separation of gameplay and why I recommend others make the switch.

Why?

Why would you want to separate out the gameplay from the rest of the game? There are a few main reasons for this:

Gameplay code varies widely between different games. Whereas other systems like rendering, audio, animations and input have many similarities between different games. (Eg while Battlefield 3 and NFS: The Run share an engine, their gameplay is substantially different).

Gameplay code has different ownership to the other systems in the game. Most teams are split into gameplay and engine divisions. These two areas require different skill sets which is why there is specialisation in each. Often the size for the gameplay team will be similar in size to the engine team.

Designers deal solely in terms of gameplay and so they should. Designers should not be concerned with shaders or specific input code. Separating this code out simplifies their job and protects them and the engine from each other.

Allows unit testing specific to gameplay code. As the test suites are gameplay focused they are simpler and easier to maintain.

“Finding the fun” is one of the hardest and most important parts of game development. By separating out gameplay developers can focus solely on this task without worrying about other engine related issues. By dealing with less code, developers have a better velocity to make changes and prototype new ideas throughout development.

How?

We’re using Unity and C# for our game development. We split the gameplay out into it’s own library (a .dll specifically). This library has no reference to Unity and is completely engine agnostic.

In theory, we could swap out Unity for XNA or another engine that is able to communicate with a .NET library.

The game engine then “includes” this library and uses it for simulating the game world. In Unity this is as simple as dragging the .dll into the project and you instantly have access to all it’s public types.One option is to make all access from the game engine into the library through interfaces. This gives you the best separation of concerns and completely decouples the game engine from the implementation of the gameplay. I did this for the first game that used this technique but have since moved away from it. I highly recommend having all communication through an interface for larger games and teams.

I’ve also used this technique in an XNA project which was also a simple process. Simply add a reference to the gameplay .dll and start coding against it.

Scripting Languages

This separation is often achieved through scripting languages. Certain behaviour within the game is exposed to designers through a scripting language like Lua. I’ve done this on a number of projects and this separation works well. I’ve also spoken about why I think C# should be used as a scripting language.

Separation of gameplay is an extension to the regular scripting language breakup. Separation of gameplay flips the classic scripting language paradigm on it’s head. Rather than exposing some functionality of the game engine to designers and gameplay programmers to create the game world. We let the designers and gameplay developers create the world and engine developers use this world.

This frees both teams up to work at full velocity initially as they build the ground work of the game. Both have set functionality they must achieve and can communicate through a simple, well defined interface. Designers can focus on implementing fun gameplay while engine coders work closely with artists to get the look and feel they want from the game.

Engines like Unity and Unreal all gameplay code is already in a scripting language (Unreal Script and C# vs the engine’s C/C++ code). However I’m arguing for taking this a step further and even within these scripting languages we create a separate library independent of any of the engine specific code. We then have three main domains within our game:

1.Gameplay specific code (eg Player ship and Torpedo)

2.Engine code specific to this game (eg Taking raw input and passing it in a nice form to gameplay specific code or shaders)

3.Engine code (for Unity and Unreal this is the C++ code we generally don’t access)

Negatives

I did find a few down sides to this approach. For games where game engine and gameplay ARE tightly linked there can be a lot of duplicated data. As the gameplay code is unaware of the engine data structures like transform must be duplicated in the gameplay code. This increases memory usage and processing as the data structures are converted.

Another downside is that some useful features of the game engine are not accessible to the gameplay. Two key features of Unity that would have been great to use were triggers and coroutines. Once again, code duplication is required if the gameplay is to use these features. (See future plans below for a solution to these issues)

Two Worlds

In effect, there are two instances of the game world. A gameplay specific instance and an engine/rendering specific instance. For complex games this separation is a good thing as it frees engine

developers to store the world in their own optimized data structures. This decoupling also simplifies the process of multi-threading the game engine as there is a distinct breakup between gameplay specific code and rendering/input code. I’ve worked on a large project which made this split after a multi-year development and while it was painful to implement once complete the teams velocity increased significantly.

Unit Testing

I spoke about unit testing in my last post and this is one of the major advantages of separation of gameplay. You can easily unit test the gameplay itself and have a suite of tests specific to making sure the gameplay is “correct”. When unit tests deal only with gameplay they can be simpler and higher code coverage can be achieved. One area I am looking at in the future is formally turning the game design document into a suite of gameplay specific unit tests. The gameplay team have complete ownership over the gameplay code and the test suite that tests it.

Future Plans

There are a few areas I plan to experiment with in the future that I haven’t had the opportunity to yet. The first is solving the issue of duplicated data between the gameplay and game engine. My thoughts on solving this problem are for the gameplay to have a reference to the game engine data structures where appropriate. For Unity3D this would be as simple as including the UnityEngine.dll.

Spatial data structures (Vector3, Quaternion, etc) can then be used directly in the gameplay. This breaks some of the abstraction between the gameplay and game engine but if done sparingly I think it will add a lot of value. Specific to Unity I’m going to experiment with creating MonoBehaviour entities within the gameplay as well to see whether this works and how badly it breaks the abstraction.

As I mentioned with Unit Tests, I’m going to look at ways of formalising the game design itself into a suite of unit tests. I’d like to experiment with Domain Specific Languages (DSLs) to make this as simple a process as possible for game designers. A DSL would also let them speak in their own language. I’ve experimented with fluent game design in the past and this is another area of interest for me.

Conclusion

What are your thoughts on separation of gameplay from the rest of the game code? Is this already achieved with scripting languages or do you see extra value with allowing gameplay developers to create the entire gameplay model themselves and have engine developers use world through an interface?(source:gamasutra


上一篇:

下一篇: