制作游戏时该如何为程序建立起一个框架?

1 条评论


  • 36

    KuroTencent Game Dev

    Kuro乌拉拉Xylt 等 36人赞同

    就个人经验来说,这是个有趣而困难的问题.

    不同处境的开发者往往习惯与从自身的开发处境出发,给出对架构以及模式的种种看法。轻量游戏,独立游戏开发者,对架构选择的权重会小一些,而对于项目前期规划严谨,开发人员众多的大型项目,架构的选择则重要得多。

    总而言之,好的架构能力将降低你日后推倒重来的风险,所以,无论你的开发规模如何,请认真审视框架的设计问题,然后做出恰到好处的设计。


    进入正题:

    框架的宏观设计

    - 数据层服务:管理好你的游戏配置数据以及应用层网络协议数据

    - 状态转移控制:使用你的设计知识,提供足够抽象和清晰的游戏流程转移控制,推荐从工作流模式开始逐步学习并扩展,阅读《流转的永恒之道》

    - 视图与数据:一个游戏通常需要使用UI,我们需要视图及其数据呈现模型,永远不要轻视MVC模式的哲学意义,它并不会因为你制作的是游戏而变得过时,就本人的项目而言,大量使用了MVVM模式

    - 对象层服务:对象是什么?对象来自于游戏设计所蕴含和**作的一切抽象、具象实体,我们需要一种服务,掌控游戏对象的生存,消亡,形态的千变万化。这是最富有挑战性,最难以总结的设计层。 如果试着总结,例如对于对象的生命周期,我们提供对象池技术;对应AI逻辑变体,我们大量使用行为树,等等。更多的,需要你自己对玩法做出深刻的洞察,并抽象出最适合游戏本身特点的对象操作服务

    框架的微观设计

    - 组件系统: 组件是现代游戏引擎较为流行的对象设计方式,一个游戏对象往往由多个可精确描述其行为的组件组合而成,组件系统提供复杂多变的组件实例,这些实例依附于对象从而为对象赋予不同的功能性。这一点,与通过释放接口编程的思想类似

    - 事件系统: 函数的功能调用,完成不同特性间的一对一通信,而事件的广播特性将提供一对多通信机制,俗话说的解耦神器便是~

    - 沙盒系统: 沙盒系统是一个你的游戏中可以描述的封闭环境,对沙盒中产生,消亡对象,约定对象的运行法则和变化限度,沙盒外的逻辑与沙盒内无任何耦合。 例如,贪吃蛇的地图类,刻画了一个沙盒,提供了移动的边界,食物等。


    这里介绍的只是海量框架模式的冰山一角,目的是引出对需求本身的洞察,需求决定了你的设计复杂程度. 

    大量的实践使你的开发能力不会掉队,而对框架设计的领悟决定你将可以超越多少人.

    以上。


    《游戏编程范式》

    《恰如其分的软件架构:风险驱动的设计方法》

    更新于 2016-12-08 01:30:20 0 条评论


  • 32

    Meta42levelpp.com

    Meta42Biobotmaliut 等 32人赞同

    我本人在游戏业从业5年了,游龄也有10年了, 做过 TA, 引擎工程师,Gameplay工程师, 主程序, 自己业余也一个人搞点游戏, 架构性的工作也一直在做,索性就帮帮题主吧。

    这是我之前写过的一套架构,目前也有不少身边项目在用,包括我现在在带的项目,是个基于Unity的热更新架构

    github: https://github.com/meta-42/UnityFramework


    ===========================================================

    另外补充一点,以下内容,我不会提到什么MVC, 单例组件,等等其他答主所说的东西,因为在我看来,这些只是战术层面的问题,以下,我想讨论以下战略层面的问题。

    原因有两个:

    1. 战术问题,需要工程洗礼,我在这里说的再多,炫技,炫名词,多过实际意义。

    2. 在思考一个架构时,一般来说是自顶向下,先抓主干,再填细节,所以战略层面是首先需要理清的, 战术层面,只是选择某种战术来达成战略目的罢了

    ============================================================


    这个问题可以拆分成三个层面来讲,因为这个三个层面的架构 都是完全不同的东西

    1.Gameplay
    2.Engine
    3.Workflow



    【Gameplay】
    我们从Unity引擎的设计理念说起,Unity是一个弯道超车的现代引擎,之所以可以弯道超车,以下两点功不可没

    1.设计理念简洁,干净,降低了入手门槛
    2.跨平台开发

    而导致题主产生这个问题的,便是第一点

    Unity整个引擎的设计都遵循着一个简单的逻辑, 引擎内核作为一个黑盒,并提供给开发者这个黑盒的主要接口,使开发者可以在就算不完全理解引擎内核的基础上
    也可以进行自己的扩展,简单来讲就是我给你一块白板,上面画什么,怎么画,由你自己决定。

    为什么说这个问题导致了题主的问题呢? 那是因为在这个理念下,引擎层便不会包含Gameplay部分的任何东西,开发者需要从头构建Gameplay. 对于已经有多年制作经验的人来说,这太好了, 我可以自己定制一套最适合我的Gameplay架构。 而对于没有制作经验的人来说,就会像题主一样,借由引擎的组件模式, 把一个个功能抽象为一个组件,挨个挂上去就是了,这样下去,游戏做大了, 就会开始觉得似乎架构上有问题了。

    那么如何解决这个问题呢??

    我的建议是,可以简单了解下一个基本的Gameplay架构有哪些东西,最好,且最容易获得的参考 是Unreal引擎的Gameplay架构。
    附个地址:https://docs.unrealengine.com/latest/CHN/Gameplay/Framework/index.html

    简单说下包含的主要方面

    1. 3C(3A游戏里 Gameplay部分代码量最大的模块): Controller,Camera,Character

    2. GameMode

    3. UI&HUD

    4. State: PlayerState, GameState


    这些东西的具体概述,我就不叙述了, 有了这个方向,有心人可以自己查了

    一般写游戏的Gameplay部分 都可以从这几个角度入手来分析。


    【Workflow】 未完,待补充

    【Engine】未完,待补充

    更新于 2016-12-13 13:02:37 4 条评论


  • 26

    xp觉得自己很牛逼的游戏开发人员

    神楽坂真冬ZombleKingdomArcadia 等 26人赞同

    我发现题主当前的状态简直和我刚毕业到游戏公司时一样,作为过来人(滑稽)我觉得我可以聊聊我的经历,应该对题主来说是比较有用的。

    在我刚进入公司时,我们技术让我用Unity做一个贪吃蛇(是不是觉得超简单?)正如所有初学者一样我做了以下几件事:

    1.  我先写了一个脚本挂在Camera上来生成场景(就是一堆nxn的Cube)
    2. 在一个GameObject上挂了一个叫Snake的脚本,在Start上创建Cube并保存在List里,这些Cube还挂载了一个SnakeBody的脚本;并在Update里面接受用户的输入并且移动这堆Cube
    3. 在一个GameObject上挂了挂了一个叫Food的脚本,该脚本提供了随机换一个位置的功能
    4. 在SnakeBody里面写了触发器,在与Food相碰时先去找Food脚本,然后让它随机一下位置然后找Snake增加一下身体长度;如果碰到自己或着墙,那就能知Snake脚本自己死掉了

    a84560c407d88d2341acd28fdcc3a5c9.png

    差不多就是这个样子,GameEnter完全不知道自己在干什么,Snake,SnakeBody和Food之间各种乱调各种找。现在看着才四个脚本相互调用好像也没有太乱,但当你的游戏有十来个脚本,各种UI,各种脚角在调用时会是一种多么可怕的场景。

    可想而言,我们公司的技术将我批评了一番,并让我去用MVC的方法想一下这东西要怎么写。于是乎,这版完全没有任务设计可言的贪吃蛇进入了第一次重构的阶段。

    在看了网上很多资料后,我其实一点也没看懂他们所谓的设计,所谓的框架是什么情况= =但是想到第一版本中三个脚本各种相互调用的混乱情况,我新加了一个脚本:EventManager

    这个脚本是做什么的呢,它里面保存着一个通过字符串为key,委托为value的字典;通过注将字符串与对应的回调关联起来。所以刚才的三个东西就变成了下面的样子:

    1. Snake的update和之前一样,还是加了一堆的控制,但把增加身子长度的方向注册进去了
    2. 把Food随机位置的方法注册进去了
    3. SnakeBody里面通过EventManager来调用以上说的两个方法

    然后就变成了这样63e4726cd5ec3ca4e9ba71807f780323.png

    这样看起来各个脚本之间都没有乱调了,随之而来的还有很多问题:

    1. 我就不能F12直接找到我要调用的方法,不好调试
    2. 如果我 A调用B的方法,B调用C的方法,难道我要一次又一次地用EventManager来调吗?
    3. 而且代码中,数据和GameObject还是绑在一起的,控制也写在GameObejct里面,想要拓展功能都不行。
    4. 技术老大要求的是采用MVC的方式去做

    这些问题依然存在,而且这种奇怪的EventManager调用方法又被技术老大批了一顿,然后告诉我其实在开发过程中往往只要降低耦合性,方便拓展和开发就行,很多所谓的设计模式反而会成有累赘。

    于是,现在要进行MVC的第三版,第三版做了以下几件事:

    1. 将原本不知道自己做做什么的GameEnter直正做成了一个游戏的入口,在开始时创建场景并实例化Snake和Food的控制器。
    2. Snake,Food并不再用MonoBehaviour来写,而是直接写成C#的类。在初始化是,由Snake来生成SnakeBody;Food来生成一个FoodCube来做为食物。在这里时,SnakeBody和FoodCube都分别有Snake和Food自己执有。
    3. SnakeBody中添加一个interface做为吃到食物时的回调,该回调由Snake实现。
    4. FoodCube中添加一个interface做为被吃到的回调,该回调由Food实现。

    现在这一版就变成了这样了0018c48d197efd09cd0ac1eff116762c.png

    这样子变成了由控制器直接去调用自己的实体,而SnakeBody和FoodCube则在有变化时反过来通知控制器去改变自己。不过上面的内容似乎还有一个问题就是数据呢?说好的MVC怎么好像只有V和C啊,关于这个问题只能说贪吃蛇这个游戏我真想不出有什么M,如果说加入计分系统的话应该就有了。

    以上就是我进入公司后学到的第一个东西;说真的这还谈不上什么框架可言,但是它提供了一个思路,就是将控制器和视图分视,然后制定通信方式(通过委托回调或着接口)。

    当开发内容变得更大时,例如我们公司做的MMOrpg,数据分为模版数据和实例数据;实例数据,游戏中的角色,UI组等又有专门的Manager来管理;而游戏中的角色还有各种分类,通过各种方式来实现增删改查,通信调用。

    以上这么多,我想说明的是什么呢。在开发过程中能够实现功能是第一步;第二步就是要想着如何重构它,如何将每个类的职能单一化;接着下就要去思考如何让各个功能之间的通信变得方便,耦合性更底,如何方便地管理数据,资源,实例。

    所有的这些都不是一步能做到的,而且光看网上各种奇怪的框架也不一对有用,因为多数东西你并不需要。只有自己一步一步写过来,一次一次自己去重构才能明白如何为游戏开发制定一个构框。

    以上说了好多都是废话,不过算是我工作以来的一点心得,希望对题主有用。大的方向楼上有很多人都说得很清楚了。

    发布于 2017-05-05 17:59:22 5 条评论 禁止转载


  • 10

    maliut手残玩家,新手码农

    琪露诺锐呱呱塔塔塔 等 10人赞同

    可以看看 游戏编程模式 ,尤其是其中的 组件模式 。组件模式是 Unity 采用的最主要的模式,了解其设计思想,知道它如何实现代码的解耦、组件间通信问题等,可以对在 Unity 下写出漂亮的代码有很大的帮助。当然它也不是万能的,面对具体的问题也要灵活应对。

    另外还是需要多写代码吧,毕竟框架、模式什么的也都是在实践中总结出来的,刚开始的程序乱一点不要紧,多写了自然也会有所感悟。希望对你有帮助。

    发布于 2016-11-23 21:34:43 0 条评论


  • 4

    怕人的流浪猫修炼的其实不是魔法而是泡茶的手艺

    strategyArcadia帕秋莉诺蕾姬 等 4人赞同

    Unity中华区讲座里面刘钢挺实在易懂的说了点,至少以前对我有启发。

    我也是一个菜鸡!个人觉得题主可以从“单例/命令/状态/观察者”四个模式获得启发。

    不过unity最大的优点就是快速原型开发,记得以前看过一句话,果断收藏:

    “游戏开发需要很多实验、探索与试错。 特别是在早期,写一些你知道要扔掉的代码是很普遍的事情。”

    想要代码干净整洁,功能实现优雅,虽然很好。但是对于我们菜鸡来说,即使想破了脑袋,还是可能设计出一坨臃肿,庞大,毫无灵活性的抽象层。

    ——当然,最关键的是它可能直到最后都没有发挥出任何作用。除了能让你在前进的过程中为了不断维护它而消耗精力。

    “预测未来很难,最终无益,那就有害。”

    个人觉得对于游戏来说,没什么比实现本身重要——

    除非你是个程序员,而非游戏开发者。

    以上。

    更新于 2016-11-24 11:26:42 0 条评论


  • 3

    iDesigning我正努力设计游戏

    前段时间刚好看了一篇文章,主要就是讲的:

    核心游戏系统架构设计

    作者在很多项目的千锤百炼下,根据个人经验总结出关于系统架构的设计,相当值得参考, http://www.aisharing.com/archives/769

    有兴趣的童鞋可以看看。 

    发布于 2016-12-08 20:28:03 0 条评论


  • 3

    木落python用户,开发者,独立游戏爱好者

    木落ArcadiaBiobot 赞同

    什么模式啥的都是胡扯,认准两个字:

    多练

    架构能力等价于推倒重来的能力,持续追求项目与代码的整洁和优雅,当发现实在做不到的时候,把这个项目推倒重来就可以了。

    发布于 2016-11-24 20:00:12 0 条评论


  • 3

    Canvas游戏一生

    乌拉拉BiobotArcadia 赞同

    讲讲两种途径来达到题主的目标

    1、完成功能不断的重构。kiss 原则(简单,模块化,通用性)

    2、看别人的架构(最好是轻量级)

    一些通用的做法:

        数据 表现 分离(但是很多时候 很难划分清楚。简单处理 只要实现功能即可,不用太多纠结)

        数据可以用单例做全局访问

        尽量用组合 而不是 继承

        核心的特殊功能 写特殊的处理方式。

        熟悉引擎的特点,可以找找文章很多人总结过。

        对Unity3d 的 monobehaviour 简单的封装一层,便于全局管理。

    发布于 2016-11-24 11:52:31 2 条评论


  • 2

    jokemon做单机游戏、HTML5游戏、手游

    jokemon菊开几世 赞同

    我认为这里有个理念问题。这事理论上不应该局限在技术本身,是需要负责人非常清晰产品需求的!

    比如独立游戏,一个人非常清楚自己该做什么,所以很多东西就自然而然知道去如何设计,如何规划。

    大项目里,负责架构的人也一定会把需求理解到位,我认为这个过程比技术实现还重要。

    而实现这个过程无非就是多练多测了。大不了推翻再来,至少先达到“满足需求”的标准~当然这里的需求肯定也包含一些技术评测指标,比如在XX手机运行100个战斗对象,200个特效要保证稳定流畅,以FPS为参考等等~

    发布于 2016-12-08 15:35:51 0 条评论


  • 2

    gt程序

    仅代表个人观点

    作为刚接触Unity的新手来说,我之前也和@怕人的流浪猫‍ 一样看过 Unity中华区讲座里面的刘钢的讲座,了解了Unity的一些框架基础的可行性。

    但是我实践到项目中,发现很多理论上的东西虽然理解但是没有一定的代码量和项目经验,很难积累起来。

    后来我用了StrangeIoC这个Unity框架,虽然说在一些性能上面会有花销,不过优点很明显

    1.  解耦效果明显(UI, Service解耦明显),代码结构更清晰了,对应需要写的功能可以直接知道你这个.cs文件应该放哪儿
    2. 整个scene的功能点更加集中,甚至来说很多scene可以做到独立运行,如果代码耦合厉害,往往运行时各种报错

    StrangeIoC给了我不少启发,代码的结构以及个人思路也清晰了不少。

    因为我用框架也才刚开始,目前给我的感受是这些,不过我想说,很多新手第一步倒不是说框架,上面很多大神也说了,应该多写,把功能出来,这样可以给人更多的成就感来继续进行游戏开发!

    发布于 2016-11-25 16:25:12 0 条评论


  • 2

    河豚被女巫陷害的猎人反杀了预言家

    河豚乌拉拉 赞同

    先把你游戏的核心功能做出来,比如战斗~

    然后再在核心的基础上加功能,比如,战斗完结算,然后从主界面进到战斗,然后登陆界面进主界面,然后发包。安卓或者PC。

    你的游戏就完整了,登陆->主界面->战斗->结算->主界面。。。

    然后再根据需求添加其他系统~

    如果你的意思是写出一个脚本,不知道怎么把各脚本关联起来。可以用管理类,可以用静态变量,用事件委托。

    比如,一开始游戏是登录界面,登录界面应该有个脚本处理登录信息,以及加载资源。然后唯一入口进去主界面,主界面应该有一个ViewManager类管理各功能模块,比如背包,装备,技能。各模块间信息交流通过事件委托。

    比如,穿上一把剑,就会获得一个技能升龙斩。那么事件委托就是当穿上装备这事件完成,告诉管理类,然后管理再告诉其他接收消息的类。然后技能模块就知道你穿了一把剑,就更新技能。或者用静态数据,比如你穿上剑,就修改人物数据。然后你打开技能模块时,读取人物数据,发现你有了一把剑,就更新技能。

    Unity是游戏引擎,如果你战斗,主界面,登录并不在一个场景,就需要用到静态数据跟类。比如你战斗的时候获得了一把剑,就修改背包数据,记录多了一把剑。然后你回到主界面进入背包,就有剑了。.

    发布于 2016-11-24 09:38:51 0 条评论


  • 1

    Sadi像素游戏票友,小翻译

    无有时代 赞同

    我的观点是多多制作

    不要期望第一次就知道哪里怎么做是最好的做法。 我业余制作了几款小游戏,基本提炼出来的一些公共库。这些公共库就是框架的一部分了。

    而框架是比如2D平台动作游戏框架,文字冒险游戏框架,飞行射击游戏框架这类可以快速帮助你开始某种类型游戏制作并且根据需求拓展。

    比如你制作一个2D平台跳跃游戏,第一次制作完成之后再制作下一款时候可以提取前面的代码进行抽象处理,重构,把不好的代码删除,可能这一次再做也不是很好,然后第三次第四次一次一次就可能把你的平台游戏框架完善。

    在编写代码时候注意可拓展性,注意解耦,注意使用事件,注意数据驱动会比较有帮助。

    归根结底还是需要经年累月的思考与积累

    发布于 2018-05-25 16:18:49 0 条评论 禁止转载


  • 1

    warmtrueVR游戏开发者

    gx36999 赞同

    学习并使用别人的框架,比如uframe,playermaker,KSFramework等等,尽量不要重复造轮子

    发布于 2016-11-25 16:05:22 0 条评论


  • 0

    wsedr-

    实体组件系统(ECS)

    https://unity3d.com/cn/unity/features/job-system-ECS

    好像效率比gameobject挂脚本的方式高。

    发布于 2018-08-09 23:31:05 0 条评论


  • 0

    MoonSir祖伟今祖龙娱乐UI/UE策划

    马克,学习一下

    发布于 2016-11-25 15:52:23 0 条评论

  • 登录奶牛关账号即可参与讨论

{{question['follower_count']}} 个玩家关注

...

相关元素

相关问题

有什么比较推荐的用Unity3D做2d游戏的教程或者源码?

10人关注 4个回答

开发测试Unity游戏用的Android平板电脑应该如何选择?

5人关注 5个回答

RenderMonkey这些老牌shader纷纷停止维护了,shader会被淘汰吗?

9人关注 5个回答

问题被以下收藏夹收录