百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 文章教程 > 正文

思考:如何设计游戏业务框架

yund56 2025-07-06 19:21 20 浏览

虽然现在连主机游戏都纷纷加入了网战部分,不过其身份主要充当状态同步,矛盾点集中在同步即时性上。以大量数值逻辑为主的业务功能侧重点则不同。如果说写代码就是用状态的操作给问题建模,那么编程范式和设计模式种种的目的就是用一种稳健的方式管理状态和划分操作权。游戏的业务部分往往状态繁多,且有很多异步操作。这么多状态没有一个行之有效的管理模式代码就成一锅汤了,这里记录一下笔者最近的思考。

游戏业务的关注点无外乎主动 get 数据并呈现,主动把界面上的输入 set 到数据,数据改变时被动刷新回界面,这三点而已。那么很容易为游戏业务按照经典的 MVP (Model Presenter View) 模式来设计框架。

在笔者的设计中,View 即业务相关 GUI,这一层的实现仅关注如何简洁的构造 GUI 及相关效果,当然,没有哪个效果会和逻辑数据耦合。

Model 包含所有业务相关数据,只对 Presenter 提供 get,set,callback 注册接口。这一层诚如 DB,Presender 并不需要关心数据从哪儿来,当前又存储在哪儿。国内游戏开发圈经历了这么多年引擎用的越来越溜恐怕没人把渲染和逻辑搅在一起了,同理网络读写也应该封装在 Model 层内部。

Presenter 是业务逻辑代码所在,负责向 View 推数据做展示,并注册用户输入处理回调;还会从 Model 层主动 get,set 数据,并接收数据改变回调。

其中 Presenter 和 View 之间的绑定属于体力活,完全可以通过内部或外部 DSL 解决,这样会省下相当多的由数据生成并填充界面,或界面操作反映到数据的代码。伪代码如下:

  1. presenter = new Presenter

  2. view = presenter.show("layout.dat")

  3. model = new Model("config.dat", network)

  4. presenter.bind(

  5. model["player/exp"],

  6. view["window/label"]

  7. )

  8. presenter.reg(

  9. model["game/fight"],

  10. view["window/button.clicked"]

  11. )

如果需要根据数据动态创建对象,则需使用 GUI 模板:

  1. presenter.bindWithTemplate(

  2. model["player/props"].where(true),

  3. view["window/panel"],

  4. "prop_item_layout.dat"

  5. )

既然被称为 DSL,就应该做到支持 where,orderby,group,join 等子句,甚至 precedure。Presenter 中会用一点点代码实现通用数据桥接器,负责被绑定到一起的 View 控件和 Model 值的转换和传递。对于注册到 Model 的 View 层动作,Presenter 同样桥接并传递给 Model。Model 中数据并不一定表示某个具象的实体,还可以是抽象的操作,比如一个对象表示“升级某个英雄”这一操作,在 DSL 中这样表示一次具体的升级操作:

  1. presenter.regWithObject(

  2. model["player/hero/upgrade_operation"],

  3. view["window/upgrade/button.clicked"],

  4. view["window/upgrade/invisible/id"]

  5. )

当然,你可以选择像我这个例子中一样使用 View 层一个纯数据、不可见对象存储当前操作的英雄 ID,也可以在 DSL 内用一个变量保存,DSL 的制定灵活得多,完全没必要拘泥。

使用脚本实现的 DSL 叫做外部 DSL,相对的使用原生语言实现的 DSL 叫做内部 DSL,但无疑主流脚本的一类函数、动态性和内置异步支持会让 DSL 更具声明式特性。

业务逻辑的特点是有很多异步操作,MVP 模式不会把异步的发起者和执行者混到一起,仅专注解决异步的两个核心问题:异步回调,以及异步互斥。这很像是在谈论异步编程模型是不是,没错,游戏业务中的异步问题简化的多,这里不存在并发的情景。我们只是在业务层面使用异步搞定数据修改发起,数据修改执行,数据读(写)互斥这三个问题,这比在底层做大规模并发容易多了。在我的设计中,只有当在 View 层的下一步操作所依赖的 Model 层数据需要等待一个异步结果时才加锁,我们一开始就已经说明,数据流向有三种,get,set 和 callback,读写只会发生在 Model 层,那么不难想到完整的异步读写访问流程如下文所述。

Set 数据时先判断是否有未完成的 set (即是否上锁),如果有则忽略当前 set 操作,注意这时不需要对 View 层锁定操作;否则对数据进行设置并加锁,锁会对关联数据同时加锁,同理,set 前亦需对关联数据判断写入操作是否已被锁定。

Get 数据时判断是否上锁,有则异步等待(通常做法在 View 层转加载圆圈并禁止操作,但不是必需的,下文会做解释),没有锁直接取数据。

数据改变的 callback 由 Model 层的网络消息触发,这一行为有可能是因 set 操作引起的,也有可能是由远端机主动触发的。对于第一种情况,因为 set 时加了锁,所以这里需要解锁对应数据(及关联数据),然后调用数据改变 callback;第二种情况中只回调即可。

还是用英雄升级举例,假定升级英雄会消耗碎片和金币,Model 层的伪代码如下:

  1. class Hero {

  2. Async Level {

  3. get {

  4. if (_locked("level"))

  5. return Async( => _level);


  6. return _level;

  7. }

  8. private set {

  9. _level = value;


  10. raiseChanged("level", _level);

  11. }

  12. }

  13. Async Gold {

  14. get {

  15. if (_locked("gold"))

  16. return Async( => _gold);


  17. return _gold;

  18. }

  19. private set {

  20. _gold = value;


  21. raiseChanged("gold", _gold);

  22. }

  23. }

  24. Async ChipCount {

  25. get {

  26. if (_locked("chip_count"))

  27. return Async( => _chipCount);


  28. return _chipCount;

  29. }

  30. private set {

  31. _chipCount = value;


  32. raiseChanged("chip_count", _chipCount);

  33. }

  34. }

  35. bool Upgradable {

  36. get {

  37. return Gold >= m && ChipCount >= n;

  38. }

  39. }

  40. void upgrade {

  41. if (!lock("upgrade"))

  42. return;

  43. network.requestUpgrade;

  44. }

  45. void upgradeResponsed(Msg data) {

  46. Level = data.level;

  47. Gold = data.gold;

  48. ChipCount = data.chipCount;

  49. unlock("upgrade");

  50. }

  51. void goldChangedNotification(Msg data) {

  52. Gold = data.gold;

  53. }

  54. bool locked(string op) {

  55. if (op == "upgrade")

  56. return _locked("upgrade") || _locked("gold") || _locked("chip_count");

  57. }

  58. bool lock(string op) {

  59. if (locked(op))

  60. return false;

  61. if (op == "upgrade") {

  62. _lock("upgrade"); _lock("gold"); _lock("chip_count"); _lock("level");


  63. return true;

  64. }

  65. }

  66. void unlock(string op) {

  67. if (op == "upgrade") {

  68. _unlock("upgrade"); _unlock("gold"); _unlock("chip_count"); _unlock("level");

  69. }

  70. }

  71. }

在 Presenter 层,get 数据和 callback 的伪代码如下:

  1. def getter(path)

  2. ret = model[path].get

  3. if (ret is Async) then

  4. schedule(ret)

  5. else

  6. return ret

  7. end if

  8. end def

  9. def callback(path, value)

  10. raise(path, value)

  11. end def


更进一步,甚至可以把 Model 层的读取时对锁的互斥去掉,立即返回本机的当前数据,在 Presenter 层也不需要对异步 getter 做延迟处理。有了写入锁,就可以保证对数据有写入的操作间的互斥,而且不阻碍玩家在 View 层忽略暂时被锁住的操作转而跳去做其他事情。没错,就像 SUPERCELL 的游戏做到的那样。除非你的界面上花了大把力气做了升级、升星、升品、道具获得等等特效,玩家非得看完才对得起你的诚意?

事情谈到这离完整的设计还差另一半,即在 Presenter 层用同步的风格写出异步的代码,这是写出清爽代码的重要因素,我能从网上找到大把各种语言的异步写法,得益于异步无刷新 Web 体验的兴趣,JavaScript 的各种技巧可能是最容易搜到的例子。而具体怎样实现依赖于你的 DSL 实现环境,以及个人风格喜好,用同步风格写异步操作的手感比零碎的函数干净多了。

相关推荐

SM小分队Girls on Top,女神战队少了f(x)?

这次由SM娱乐公司在冬季即将开演的smtown里,将公司的所有女团成员集结成了一个小分队project。第一位这是全面ACE的大姐成员权宝儿(BoA),出道二十年,在日本单人销量过千万,韩国国内200...

韩国女团 aespa 首场 VR 演唱会或暗示 Quest 3 将于 10 月推出

AmazeVR宣布将在十月份举办一场现场VR音乐会,观众将佩戴MetaQuest3进行体验。韩国女团aespa于2020年11月出道,此后在日本推出了三张金唱片,在韩国推出了...

韩网热议!女团aespa成员Giselle在长腿爱豆中真的是legend

身高163的Giselle,长腿傲人,身材比例绝了...

假唱而被骂爆的女团:IVE、NewJeans、aespa上榜

在韩国,其实K-pop偶像并不被认为是真正的歌手,因为偶像们必须兼备舞蹈能力、也经常透过对嘴来完成舞台。由于科技的日渐发达,也有许多网友会利用消音软体来验证K-pop偶像到底有没有开麦唱歌,导致假唱这...

新女团Aespa登时尚大片 四个少女四种style

来源:环球网

韩国女团aespa新歌MV曝光 画面梦幻造型超美

12月20日,韩国女团aespa翻唱曲《DreamsComeTrue》MV公开,视频中,她们的造型超美!WINTER背后长出一双梦幻般的翅膀。柳智敏笑容甜美。宁艺卓皮肤白皙。GISELLE五官精致...

女网友向拳头维权,自称是萨勒芬妮的原型?某韩国女团抄袭KDA

女英雄萨勒芬妮(Seraphine)是拳头在2020年推出的第五位新英雄,在还没有正式上线时就备受lsp玩家的关注,因为她实在是太可爱了。和其他新英雄不同的是,萨勒芬妮在没上线时就被拳头当成虚拟偶像来...

人气TOP女团是?INS粉丝数见分晓;TWICE成员为何在演唱会落泪?

现在的人气TOP女团是?INS粉丝数见分晓!现在爱豆和粉丝之间的交流方法变得多种多样,但是Instagram依然是主要的交流手段。很多粉丝根据粉丝数评价偶像的人气,拥有数百、数千万粉丝的组合作为全球偶...

韩国女团MVaespa Drama MV_韩国女团穿超短裙子跳舞

WelcometoDrama.Pleasefollow4ruleswhilewatchingtheDrama.·1)Lookbackimmediatelywhenyoufe...

aespa师妹团今年将出道! SM职员亲口曝「新女团风格、人数」

记者刘宛欣/综合报导南韩造星工厂SM娱乐曾打造出东方神起、SUPERJUNIOR、少女时代、SHINee、EXO等传奇团体,近年推出的aespa、RIIZE更是双双成为新生代一线团体,深受大众与粉丝...

南韩最活跃的女团aespa,新专辑《Girls》即将发布,盘点昔日经典

女团aespa歌曲盘点,新专辑《Girls》即将发布,期待大火。明天也就是2022年的7月8号,aespa新专辑《Girls》即将发行。这是继首张专辑《Savage》之后,时隔19个月的第二张专辑,这...

章泽天女团aespa出席戛纳晚宴 宋康昊携新片亮相

搜狐娱乐讯(山今/文玄反影/图科明/视频)法国时间5月23日晚,女团aespa、宋康昊、章泽天等明星亮相戛纳晚宴。章泽天身姿优越。章泽天肩颈线优越。章泽天双臂纤细。章泽天仪态端正。女团aespa亮...

Aespa舞台暴露身高比例,宁艺卓脸大,柳智敏有“TOP”相

作为SM公司最新女团aespa,初舞台《BlackMamba》公开,在初舞台里,看得出来SM公司是下了大功夫的,虽然之前SM公司新出的女团都有很长的先导片,但是aespa显然是有“特殊待遇”。运用了...

AESPA女团成员柳智敏karina大美女

真队内速度最快最火达成队内首个且唯一两百万点赞五代男女团中输断层第一(图转自微博)...

对来学校演出的女团成员语言性骚扰?韩国这所男高的学生恶心透了

哕了……本月4日,景福男子高中相关人士称已经找到了在SNS中上传对aespa成员进行性骚扰文章的学生,并开始着手调查。2日,SM娱乐创始人李秀满的母校——景福高中迎来了建校101周年庆典活动。当天,S...