分享一下以前做游戏前端开发的思考

2,708 阅读11分钟

本文是最近几年的零星几篇笔记拼凑而成的。每次都是有些感悟,然后记下来,导致每一篇笔记都是零散的。 多亏了现在有了GPT,否则,我的笔记也不会重见天日了:

  1. “下面的文字是我之前写的笔记,我们称呼这篇笔记叫做A:....,请你总结一下上面的内容,并输出不少于2000字的博客。风格要与笔记A相似,不要太“AI”化。”
  2. “这篇文章内容非常割裂,逻辑不够连贯。请帮忙重新输出,字数1500字以上”
  3. “这个总结丢失了很多细节。对于笔记A的原文,不做删减。根据你的理解,调整一下结构,让逻辑更加通顺。”

本文行文比较陡峭,有些地方我也觉得很费解,但是自己回想了当时情景,又通顺了。

整体来说,通过GPT-4o的帮助,本文还是很好的保留了笔记的原貌。

f34248588b5e41ddb573e679fd24bbe0.png

一、背景

经历了几家公司,同事都是来自于各个大小厂。发现说到游戏架构,很多人没有思路。即使是有思路,也只是进行简单的模块拆解,比如使用什么开发框架,业务分为几个模块。或者有些更进一步的,稍微做一下分层。再接着聊,基本都会说到一些技术难点,比如图形算法,音视频处理等。

二、问题所在

1. 只有模块,不做抽象

以上几种只是对当前业务场景的简单模块划分,基本上每个模块都有一个单例入口类,然后外部持有单例进行调用。所以,以上的分享应该不能称之为架构。游戏前端,也是前端。也需要应对“现代前端”对项目的要求。

2. 只阐述功能,不阐述原理

许多分享只关注功能的实现,而没有解释背后的原理。这导致当功能出现问题时,开发者往往无法通过理解原理来解决问题。

3. 设计模式与游戏开发

设计模式是软件开发思想的总结。基本上我们写的所有项目都透着设计模式的香味。有意识的人,可能会区分香味来源在哪里;一些人,却总觉得这个香味很棒,却不知道怎么去提炼,提取,最后香味变成了一个屁。我们推荐使用设计模式。能用的地方,要尽量去用。不要想着自己能创造一些非同凡响的思路,除非你真的梳理过人类创造的各种思想,发现无法匹配你当前的所想所思,你“独创”了这种“设计模式”。

使用设计模式,可以使你的代码结构清晰地展示在读者面前。他人不需要特别费力地思考,就可以很快地捋顺你的思路。这里要做什么,那里是做什么。举个简单的例子,比如“享元模式”,为了实现创建对象的时候,能复用以前的对象。我们看看游戏里面怎么去命名这个模式的,“对象池”——换做别的行业的人,可能还要重新看一遍你的代码,猜猜你这个对象池究竟是做什么的。而如果命名为“享元模式”,那么,无论什么行业,都可以快速理解这个文件解决了哪些问题。当然,每个设计模式实现的方法并没有唯一的表现,我们只要知道这个我们用了这个模式,根据我们的业务稍微改变了一些地方,仅此而已。

三、什么是软件架构

1. 什么是架构

软件架构是对系统结构和行为的抽象描述,涵盖了模块的划分及其相互关系、设计原则、模式和策略等。良好的软件架构不仅能提高系统的可维护性和可扩展性,还能提升开发效率和质量。

2. 现在游戏公司架构

目前,许多游戏公司在架构设计上仍处于初级阶段,缺乏系统性和规范性。尤其在一些小公司,由于资源和时间的限制,架构设计往往被忽略,导致后期维护和扩展困难。

3. 游戏需要解决的需求

提升开发体验(ECS,蓝图),处理大量的图形渲染、音视频处理和实时交互,更高的性能和响应速度。

四、游戏前端的特殊之处

游戏前端开发与传统前端开发虽然有相似之处,但也有其独特的特点。游戏前端需要与游戏引擎紧密结合,处理大量的图形渲染和实时交互,要求代码高度优化,以确保游戏流畅运行。

五、为什么没有新的理论模型

游戏公司没有基因,游戏人被“锁死”。游戏行业的“狼性”文化、急功近利的公司基因、全行业“赛马”文化、频繁的“996”工作模式,以及对引擎工具链的依赖,导致了很多公司缺乏创新和理论模型的开发。

  1. 公司文化,讲“狼性”
  2. 公司基因,急功近利
  3. 全行业“赛马”,看谁抄的快,造成工作强度大,“996”文化盛行(比如上海很多做传奇类的,都是这种)
  4. 大多数项目,上线就是死亡
  5. 没有完善的职业培训
  6. 吸收不到优秀的人才(为什么游戏行业没有top学校的人才)
  7. 大公司山头林立,很多既得利益者
  8. 围绕引擎提供的工具链,开发人员很多技能树被锁死,不需要知道太多,只需要记住API就可以快速开发迭代
  9. 行业内卷,“教会徒弟,饿死师傅”,老公司少有价值输出(搜论文库,垂直行业里面游戏论文屈指可数)

六、记录项目中遇到的事情

1. 初入项目

项目是做在线教育的,已经开发有三年多时间。现在需要把以前的东西重新推翻。三年前立项的时候,由于版本的迭代,将很多东西都揉到了一起,导致后面扩展的时候非常困难。项目里面的游戏都是一些微型的单机小游戏,然后将UI设置为动态换皮。策划或者产品人员,通过一个JSON配置,来对不同的游戏进行皮肤设置。项目中有很多的游戏类型,都是分割开来的。根据配置,动态地设置路由,跳转到不同的游戏类型上去。当新增游戏类型的时候,就要动态地添加游戏类型,创建一个新的游戏。假设两个游戏比较相似,如果改动比较大,则新建游戏类型;如果改动比较小,则在原来游戏的类型上。

新的需求是要做成像UE4蓝图那样的,产品通过拖拽组件,设置一些属性,通过连线设置组件动作,最终生成配置,来生成不同的游戏。项目人员都是做Cocos开发的。

2. 架构设计

入组以前,老员工已经想好了怎么设计。通过Web编辑器+Cocos组件的形式,来满足需求。Web编辑器模拟蓝图的UI部分,Cocos来根据蓝图生成配置,生成需要的游戏。Cocos这边只有一篇文档,画了一个简陋的架构图。大致思路是:参考ECS的思路,将组件原子化,将能力挂在Node节点上,当触发某些动作的时候,执行一系列的命令(CMD)。

3. 实施

主程序根据以前的项目架子,将游戏分成了几个模块,每个模块负责独立的事情。

4. 分层

无论怎么开始,都要强制分层!!!写代码并没有特别严格的限制,我们可以挥毫笔墨,挥斥方遒。当过了一段时间,别人看你写的代码的时候,根本不知道从何看起。依旧是”逆向分析“你的思路。甚至于自己再回头看自己写的代码,也是一坨坨的,不忍直视。想要书写一段佳话在你以前的代码里,怎么看都是“给屎雕花”。分层后,可以保证你的底层逻辑是可以被阅读的,可以被传承的。依赖于你底层提供的接口,上层的业务也有了“逆向分析”的起点。我们在对代码进行逆向分析的时候,一般都是从“入口”“出口”来打断点,看对应的逻辑走向,调用堆栈。如果没有底层代码,在拍平的代码环境下,设置都找不到入口出口。

5. MVC?NO!!!

MVC属于设计思想,没有固定的格式。只要拥有M、V、C这三部分,就可以称呼为MVC。MVC主要是解决开发人员开发代码的时候,模块划分不清晰,职责分配不明确。以此来强制约束开发人员按照固定的“模板”来写代码,使代码清晰、可维护。我们当前项目并没有按照“经典MVC”进行划分,只在书写的时候,将其作为一个参考。我们的设计架构可以称呼为“ETC"——Entity Trigger Command。我们梳理的当前,以及过往所有项目,其实GUI编程的本质可以归纳为一句话——一个实体触发了一系列动作。这个实体可能出生的时候就触发了一串动作,也可能是被鼠标/接触而触发了一串动作。比如,一个简单页面www.baidu.com,实体是所有可见元素。当页面加载成功后,所有实体静态展示:实体&加载成功&静态展示;当鼠标移动到搜索按钮,按钮闪动: 按钮&鼠标交互&闪动;当点击搜索:搜索按钮&鼠标交互&搜索关键字;我们发现,几乎所有的交互都可以通过ETC的方式来处理。所以,我们认为在GUI编程中,ETC是所有架构设计的基础。如果你发现当前架构设计已经不能承受目前的业务量,那么,你一定是没有做好ETC,才造成了当前的问题。

6. 命令模式

命令模式在ETC中起到了很大的作用。通过命令模式,可以解耦每个模块间的联系。游戏中有很多交互,比如一个按钮的点击,可能会涉及到多个模块的改变,甚至业务处理。所以,命令模式很大程度上解耦了我们之间的关系,保证了代码的可读性和可维护性。我们再来看一个实例,某个游戏项目里面,用户点击某个按钮,增加了10点经验值;当经验值满了后,用户升级,同时显示升级特效;当用户升级后,触发了一系列奖励;奖励需要通过邮件系统发放给用户,同时更新用户信息。假设我们没有使用命令模式,这些逻辑可能都要写在一个函数里面,使得代码非常臃肿,难以维护。使用命令模式后,我们可以将每个逻辑拆分成独立的命令类,通过命令模式进行调用,使代码结构清晰,易于维护。

七、方法论与总结

我们通过不断的实践,总结了一些方法论,希望能够对大家有所帮助。

1. 强制分层

分层可以使代码结构清晰,提高代码的可维护性。通过分层,我们可以将底层逻辑与业务逻辑分离,便于代码的扩展和重构。

2. 设计模式

设计模式是软件开发思想的总结,能用的地方要尽量去用。不要想着自己能创造一些非同凡响的思路,除非你真的梳理过人类创造的各种思想,发现无法匹配你当前的所想所思,你“独创”了这种“设计模式”。

3. ETC(Entity Trigger Command)

我们认为在GUI编程中,ETC是所有架构设计的基础。如果你发现当前架构设计已经不能承受目前的业务量,那么,你一定是没有做好ETC,才造成了当前的问题。

4. 谨记一条:单一职责原则

面向对象设计中,单一职责原则强调每个类应只有一个引起变化的原因,即每个类只负责一个功能。这有助于提高代码的可维护性和可扩展性。在游戏开发中,应尽量将功能模块化,每个模块只负责单一职责。

5. 理论与实践结合

在软件工程方面,很多实践都是“重复前人”,基本上都有理论支撑。“能抄就抄,不要从头开始”。

结语

不要搞游戏前端开发了,不是人干的。