咱们在游戏设计和开发中,尤为是引擎开发中,逻辑循环是一个重要组成部分,循环决定了游戏的基础逻辑和运行方式,在不一样的开发环境和语言下,对于循环的释义甚至相差甚远,那么我想和你们分享的是在Silverlight游戏开发中,循环的设计方式和作法。算法
如下内容来自以往的游戏开发经验,可能在其余语言中的相关文章更加详细,谨在这里讨论有关在Silverlight游戏开发中的应用。设计模式
在传统的开发观念中,不管任何开发环境,它都逃不出While,代码通常是这样:数组
while (true) { if (GameExit() == true) break; else GameLoop(); }
这个代码方式只是一个模型,能够将其理解成为一个不停在检查状态的状态机。安全
那么在Silverlight游戏开发中,咱们是否也能够这样应用呢?道理上差很少,目前来讲大部分的作法只是实现了一个根(Root)部,这方面深蓝色右手以及不少其余朋友都有了各类各样的解决方案,有兴趣的朋友能够找他们的文章,不管是用线程(Thread)、故事板(Storyboard)、Rendering、DispatcherTimer,都是一个好的循环体的开始。网络
对于游戏而言,尤为是网络游戏,咱们将面临着大量的交互,这些交互可能来自用户,也可能来自自身的游戏逻辑,就如最现实的问题是,当一个游戏的同屏幕呈现100个以上的角色的时候,游戏是否所以而“卡”住,在早期的时候,我陷入了一个误区,呈现足够多的角色就是最大的性能体现(3.0呈现600个角色不卡),如今看来倒是否则,由于单纯的角色呈现,有几百个不算什么,在一个总体游戏的执行时候,它是否还能保持足够的流畅才是最重要的,由于战斗逻辑、界面逻辑、场景管理器无时不刻在占用着系统资源,而且此时的角色也绝非几张图片那么简单,他们身上的装备、部件、特效都将成为游戏开发者的负担。数据结构
在此种状况下,优化循环过程至关重要,做为团队经验积累,今次拿出来你们一块儿研讨,有什么好的想法和建议欢迎一块儿交流一下:)下面的五种循环设计模式名字本身乱起的很差,还请见谅。oop
自身式循环比较容易理解,好比一个精灵控件,本身内部实现一个循环,来不停的检测和执行逻辑,开发者都不须要去单独作什么,只须要new出来它们本身就会执行逻辑了,这种方式很是便捷和方便,开发起来也相对容易,互相之间没有任何关系,此时须要借助单例之类的设计模式来解决互相的结合问题。图示以下:性能
很显然,咱们自身逻辑有一个最大的问题是独自的性能占用,若是一个场景(不是同屏)有几百个这样的循环时,那么游戏各个线程就会吃掉大量的CPU,尤为是用Thread、Storyboard、DispatcherTimer的时候。优化
自身逻辑存在各自的循环消耗问题,那么有没有办法将各自的循环逻辑统一到一个循环中呢,若是学过数据结构,咱们能够透过链表的形式来作,基本的原理是将各个循环体放入到一个大循环中,而后从第一个开始执行循环逻辑,只执行一次,而后下一个,到底之后回来继续执行,模型以下:动画
这是一种常见的处理方法,可以大大下降系统消耗,并且C#提供了迭代器等好用的遍历,使得咱们结合面向对象的思路更方便。示意代码以下:
public class obj { public virtual void OnLogic(); } List<obj> ObjList = new List<obj>(); public void OnLoop() { foreach (var item in ObjList) { item.OnLogic(); } }
链条式循环最大的优势是将全部的独立循环所有集中到一个大循环逻辑中,须要注意的有一个问题,那就是动态处理,由于游戏当中的物体生成和销毁是很是频繁的,正在循环的时候发生了集合改变,那么就危险了,咱们的作法有两种,分别是数组转换和回收判断,数组转换很是容易,将集合拷贝到一个数组中,而后循环数组的各个元素;回收判断是经过标识将物体,在合适的时机摘出到一个回收列表中,而后在安全的时机清理。
链条式循环的优势能够创造一个游戏的RootHead,将全部的元素加入到这个RootHead当中,建立一个主循环而后遍历便可,固然了,你须要经过基类的方式来达到目的。
这是一种好的方式吗?在某种状况是的,它能解决性能损耗,固然了,要是内部实现的逻辑过于复杂,有的时候可能还得借助一下另外线程。在游戏产品中,有一个更加直接的需求,那就是级别层次问题,也就是说,有的循环体是系统级别,而有的可能只是一张图片,那么游戏的循环到底有多大才能包容一切,好比场景管理中的那么多场景物体,若是有逻辑循环就直接加入到这个大循环中吗?在游戏运行时,有一些循环在特定的时候是不须要使用的,或者不须要执行的,也为后续开发形成了障碍,因此,在咱们的MMOROG引擎中,最多应用是下面的这种循环模式。
子树循环顾名思义,使用树状结构来处理循环逻辑,咱们实际应用中还有能够分为:活动子树式循环和固定子树循环,为了方便讲解,主要讲固定子树循环的模式。
咱们知道在一个游戏中,有不少的系统,好比场景系统、战斗系统、队伍系统、公会系统、聊天系统……N多系统,它们本身内部是否有一个循环呢?若是从直观角度上,上述系统可能不须要循环,可是事实否则,好比队伍系统,可能为了完成组队、移动等行为,专门有一个循环来处理判断逻辑,虽然这个逻辑很简单,再好比公会系统是否有每10秒钟刷新一下公会列表的需求……
如上图所示,咱们利用子对象的方式创造一颗树,而后逐一进行遍历,在执行过程可使用迭代,也可使用递归,无论那种方式,对于子树而言没有太大的区别,可是对于性能而言,咱们能够作一些有趣的优化,当一个系统关闭的时候,它在树中就不执行了——具体用什么方法,看状况而定,不管是拆枝仍是逻辑断定都行。咱们获得的效果是,关闭的子树下面的元素也不会执行循环,多么简单,比链条式的容易多了,一断全都断。
子树式循环在系统级别很是经常使用,对于那些比较频繁的更换的逻辑比较实用,好比特效动画、地图系统等等,具体的算法和操做在《数据结构》中有明确的答案,能够在其中找到想要的东西:)。
区间式循环严格意义上是循环中的一个断定方式,而不是实现模式,原理是将游戏系统各个部分拆分开,挂入不一样的循环结构中,若是说链条式和子树式是一种Object集中,区间式能够说是一种Objects集合打散,释义图以下:
区间式在大系统级别,能够分拆最消耗性能的部分,到另一个线程(或循环结构)中完成循环,好比说战斗系统、地图处理、场景管理器,而场景管理器下也能够带入一个区间式循环,将场景分割,而后对一个区域范围的物体进行处理(若是想一想上面的图是否能够作成一个二维数组呢?),对于超出区域范围内的循环逻辑彻底视而不见就好了,不然的话,要处理一片大场景中的N多个角色,不管是在自身、链条、子树都会一笔不小的开销。
区间式最大的优势是增强了范围断定,若是写的好,还能够多重结合,使用二维(三维也行)数组完成各个须要循环逻辑的分配,将不须要的拆分出去,这里的算法可能稍微有点意思,相似哈希和List的结合,要注意的是当一个物体(OBJ)从区间1到区间2的时候,会发生什么事情:)
其实组合式循环是一个很是偷懒的部分,由于组合的是前四种而已,在游戏开发中,并非上述的那种方式最好,而是因地制宜,什么样的模式知足什么样的需求,不能只是单纯为了达到高效而高效,更加要注意将来开发的顺利程度,避免返工。
如上图所示,咱们能够很清楚的分析不一样循环方式在不一样的环境下的应用:
自身式循环比较适合界面,由于比较固定,并且复杂逻辑很少,固然了这只是在Silverlight的UI当中比较适用,其实主逻辑就是一个很大的自身循环,Root的循环方式就是一个自身式循环。
链条式循环比较使用与第二级的游戏系统,将系统所有串起来,以达到快速遍历目的,可是在系统的下一级,就是子树式循环,系统元素所有在一个系统下,下面的子树中也可能会出现链条式,很显然是一种最频繁的组合方式。
区间式循环主要是应用在场景系统,可能须要一个链条循环或者子树循环带动,具体状况须要看游戏的设计模式,若是单个场景(好比地图)是使用单例的方式,那么使用链条式循环带动循环逻辑比较合适,若是单个场景是经过new出来的,那么使用子树方式来切换衔接更加容易明了。
以上是咱们在作MMORPG时候的一些小小经验总结,上述中咱们用的最可能是组合式循环(废话,组合式全包了),可是对于一些小型的游戏,建议仍是不要设计这么复杂,对于大型的网络游戏而言,程序设计这部分的重要性非比寻常,最后,看过不少这样或那样的说法,网页游戏对于性能是不行的,我想大部分的性能问题并非技术自己,而是开发者没有将一个游戏本质思考清楚,何时咱们用什么方法能够达到什么目的,能为各位开发者多能从中找到一点灵感,那为我本身的想法也有了一个交代,也欢迎小伙伴们在评论下方留言,共同讨论。