在使用诸如C#之类的托管语言为PC编写游戏时,遇到了什么陷阱?如何解决这些陷阱?
在使用诸如C#之类的托管语言为PC编写游戏时,遇到了什么陷阱?如何解决这些陷阱?
Answers:
我对java不太了解,所以这是从.net开发人员的角度来看的。
迄今为止最大的垃圾是垃圾。Windows上的.net垃圾收集器做的很棒,您可以在没有宝宝坐大部分时间的情况下摆脱困境。在xbox / winPhone7上是另一回事。如果每隔几帧就会出现停顿,则垃圾收集可能会导致您遇到问题。目前,它每分配1mb就会触发一次。
这里是一些处理垃圾的技巧。您实际上不必担心其中的大多数,但是有一天它们可能会派上用场。
GC.GetTotalMemory()
到屏幕上。这使您可以大致估算出游戏使用的已分配字节数。如果几乎不动,那您就没事了。如果上升速度很快,那么您就会遇到问题。GC.Collect()
每帧都打电话。保持垃圾和所有这些东西似乎是一个好主意,但请记住,唯一比垃圾收集更糟糕的是垃圾收集。StringBuilder
(请注意,StringBuilder
这不是魔术子弹,并且仍然可能导致分配!!这意味着简单的操作,例如在字符串末尾添加数字会产生大量垃圾)或使用foreach
循环在使用该集合IEnumerable
接口也可以在你自己知道创建垃圾(例如,foreach (EffectPass pass in effect.CurrentTechnique.Passes)
是常见的一种)IDisposable
在包含非托管资源的类上使用。您可以使用它们清理GC无法释放的内存。要考虑的另一件事是浮点性能。尽管.Net JITer进行了大量特定于处理器的优化,但它不能使用SSE或任何其他SIMD指令集来加快浮点数学运算的速度。这会导致C ++和C#游戏之间的速度差异很大。如果您使用Mono,则可以使用一些特殊的SIMD数学库。
典型的性能陷阱是在游戏的设计/开发中不考虑垃圾收集器。产生过多的垃圾会导致游戏中出现“打h”,这会在GC运行相当长的时间时发生。
对于C#,使用值对象和“ using”语句可以减轻来自GC的压力。
using
语句与垃圾回收无关!它用于IDisposable
对象-用于释放非托管资源(即:那些未由垃圾收集器处理的资源)。
我想说我用C#编写游戏时遇到的最大问题是缺少像样的库。我发现的大多数端口都是直接端口,但不完整,或者是C ++库的包装器,因此封送处理会严重降低性能。(我专门针对OGRE库谈论MOgre和Axiom,而针对Bullet物理库谈论BulletSharp)
如果您对导致语言变慢的原因(封送处理,垃圾回收)有充分的了解,那么托管语言(与解释语言不同-Java和C#都不再进行解释了)可以和本地语言一样快。我认为真正的问题是图书馆开发人员尚未意识到这一点。
不解释C#和Java。它们被编译为中间字节码,在JIT之后,该字节码变得与本地代码一样快(或几乎可以忽略不计)。
我发现最大的陷阱是释放直接影响用户体验的资源。这些语言不会像C ++那样自动支持确定性终结处理,如果您不希望这样做,则会导致诸如网格物体之类的东西在您认为被破坏后漂浮在场景中。(C#通过IDisposable完成确定性终结,我不确定Java会做什么。)
除此之外,托管语言实际上具有处理游戏所需性能的能力,远胜于他们所赞誉的语言。编写良好的托管代码要比编写不良的本机代码快得多。
IDisposable
允许确定性清除时间紧迫且不受管理的资源,但不会直接影响终结处理或垃圾收集器。
Java和C#都不会被解释。它们都被编译成本机代码。
它们和游戏的最大问题是必须进行编码,以使它们在游戏过程中永远不会垃圾收集。您必须跳过的滚铁环的数量几乎超过了首先使用滚铁环的好处。在游戏编程中,必须避免使那些语言有趣的用于应用程序或服务器编程的大多数功能,否则在游戏进行和垃圾收集时,您会在游戏过程中长时间停顿。
通过使用此类语言(或使用诸如XNA,TorqueX引擎等工具)制作游戏时,我看到一个很大的陷阱,那就是很难找到一支拥有优秀专家的优秀团队,他们需要具备与之等效的游戏技能。在C ++和OpenGL / DirectX中找到人非常容易。
游戏开发行业仍然非常沉迷于C ++,因为用于推出大型或精打细算的小型游戏的大多数工具和管道都是用C ++编写的,据我所知,您可以使用所有官方开发工具包针对XBox,PS3和Wii的发行版仅与C ++兼容(现在XBox工具集可能会得到更多管理,有人知道吗?)
如果您现在想为游戏机开发游戏,您几乎可以在XBox上获得XNA和C#,然后仅在游戏库的一个名为XBox Live Indie Games的侧面部分获得。一些赢得比赛等的人会被选择将他们的游戏移植到真正的XBox Live Arcade。除此之外,还没有为PC制作游戏的计划。