9280打开exe提示停止工作游戏就提示 已停止

热门文章排行
宽带山热帖排行三星手机9280支持游戏手柄吗_百度知道
三星手机9280支持游戏手柄吗
我有更好的答案
com/zhidao/wh%3D600%2C800/sign=56fc6d087f32dad26d1c2/f60fd9f9d72aa0fe.jpg" esrc="http://d.hiphotos.jpg" target="_blank" title="点击查看大图" class="ikqb_img_alink"><img class="ikqb_img" src="http://d.hiphotos是可以支持使用的,就是需要先保证手机上获取下最高的root权限到手机上就好了.baidu://d。再从手机上安装下来手柄就正常使用了。<a href="http,从电脑上工具箱上的Kingroot设置进行权限获取到手机上。从而这样就让手机上获取到稳定的root权限了呢。将应用宝这个软件安装到电脑上.hiphotos.baidu.com/zhidao/pic/item/f60fd9f9d72aa0fe.baidu
采纳率:89%
为您推荐:
其他类似问题
您可能关注的内容
&#xe675;换一换
回答问题,赢新手礼包&#xe6b9;
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。iTunes11怎么安装游戏阿,~已下载完游戏!_百度知道
iTunes11怎么安装游戏阿,~已下载完游戏!
郁闷郁闷郁闷,真心不会弄着版本!~!求图文解说~!
我有更好的答案
采纳率:76%
来自团队:
为您推荐:
其他类似问题
您可能关注的内容
&#xe675;换一换
回答问题,赢新手礼包&#xe6b9;
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。&figure&&img src=&https://pic1.zhimg.com/v2-e4d3c32aedc9d573e6101d_b.jpg& data-rawwidth=&512& data-rawheight=&288& class=&origin_image zh-lightbox-thumb& width=&512& data-original=&https://pic1.zhimg.com/v2-e4d3c32aedc9d573e6101d_r.jpg&&&/figure&&p&&i&这是我之前在cowlevel中写的一篇回答。&/i&&/p&&p&&i&这个专栏刚刚开辟,内容少的惨不忍睹,所以搬运了过来。&a href=&http://link.zhihu.com/?target=http%3A//store.steampowered.com/app/650780/AngerForce_Reloaded/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&AngerForce: Reloaded&/a&在开发过程当中有一些有意思的事情比较值得记录,后面有时间的时候,我会慢慢整理出来。这里先提前挖个坑。&/i&&/p&&p&&i&cowlevel的提问是“&a href=&http://link.zhihu.com/?target=https%3A//cowlevel.net/question/1861476& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&如何为2D游戏做出空间感、3D感?&/a&”,以下是原回答,略有删减。&/i&&/p&&hr&&p&有的奶牛提到了光影、视差场景、还有一些动画技术。我也分享一些自己的经验。 &/p&&p&&br&&/p&&h2&针对静态素材:&/h2&&ol&&li&透视准确。 &/li&&li&不同层级的对象位置得当。 &/li&&li&适当的光线和阴影。 &/li&&/ol&&p&素材其实是基础,如果2D的素材绘制的问题一堆,将很难做出好的效果。 &/p&&p&&br&&/p&&h2&动画实现上的一些技巧: &/h2&&ol&&li&动画对象的部件充分拆解。 &/li&&li&Free Form Deformation。(近几年非常流行的2D动画技术,不太清楚官称是什么。我们使用Spine作为动画解决方案,官网上这么叫的。上面有奶牛提到了。我也听过一些其他名字:Live2D、网格形变动画、Mesh动画、XX变形等等等等无所谓叫什么,总之是指通过变形2d纹理来实现动画的技术。) &/li&&li&适当设计“遮蔽物”(障眼法)。 &/li&&li&混合位移和部件关键帧,制造整体的立体效果。 &/li&&li&必要时使用一些3D技术进行辅助。 &/li&&/ol&&p&场景方面已经有奶牛提到了视差滚动场景、动态光源、阴影等内容,我知道就这么多也就不献丑了。单位的动画我结合自己的游戏举些例子吧。 &/p&&p&&br&&/p&&p&我们的游戏(AngerForce-Reloaded)是一个2D的顶视角纵版卷轴射击游戏,九十年代调调的STG(简单说就是打飞机(??ω?`) ),一些方案希望可以对其他开发者有参考作用。&/p&&h2&动画对象充分拆解&/h2&&p&2D的骨骼动画要出效果,需要把单位拆解成足够细分的单元,这样制作动画时分开操作不同关节可以表现出良好的前后层关系,制造3D的错觉。 &/p&&figure&&img src=&https://pic4.zhimg.com/v2-e80a98d2ba_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&286& data-rawheight=&512& data-thumbnail=&https://pic3.zhimg.com/v2-e80a98d2ba_b.jpg& class=&content_image& width=&286&&&/figure&&p&上图是近些年比较流行的动态角色立绘;&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-ccc92e86d0654dfecda0e23a_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&256& data-rawheight=&256& class=&content_image& width=&256&&&/figure&&p&这是动画所用的Atlas。这个动画有用到Free Form Deformation,用于模拟3D状态下的关节透视变化时的形态,比如,乳摇……&/p&&p&&br&&/p&&h2&&b&自由网格形变Free Form Deformation&/b&&/h2&&p&这项功能目前主流的动画编辑工具基本都有支持,技术上没有什么难点。&/p&&p&&br&&/p&&p&我们为游戏中的每个Boss设计了一个这样的出场动画,类似九十年代电影的角色介绍。&/p&&figure&&img src=&https://pic2.zhimg.com/v2-67c19bccb50_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&180& data-rawheight=&283& data-thumbnail=&https://pic1.zhimg.com/v2-67c19bccb50_b.jpg& class=&content_image& width=&180&&&/figure&&p&这部分我们采用Free Form Deformation模拟制造了一个近似3D的转身的动画。这个角色设定上有很多规整的几何图形,在进行形变时产生了非常好的效果,甚至有同学以为我们的游戏是3D实现的,实际上只用一张纹理。&/p&&figure&&img src=&https://pic4.zhimg.com/v2-0c2f3f289e5c4b4c7257_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&319& data-rawheight=&256& class=&content_image& width=&319&&&/figure&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-f8ef2f3d31bd_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&512& data-rawheight=&128& class=&origin_image zh-lightbox-thumb& width=&512& data-original=&https://pic2.zhimg.com/v2-f8ef2f3d31bd_r.jpg&&&/figure&&p&这是纹理的网格方案和所用Atlas。&/p&&figure&&img src=&https://pic4.zhimg.com/v2-c46cbf4a3ce0_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&256& data-rawheight=&223& data-thumbnail=&https://pic1.zhimg.com/v2-c46cbf4a3ce0_b.jpg& class=&content_image& width=&256&&&/figure&&p&这个动画单独播放是这样的效果,如果仔细看还是有很多瑕疵的,能够发现并不是由3D实现的,但在游戏实际应用中,由于动画播放时间很短,足够以假乱真。&/p&&p&Free Form Deformation的原理很简单,但具体实现所展现出的效果取决于上面提到过的因素:透视准确、适当的阴影、前后层部件适当的缩放和位移、运动规律以及充分的拆解。&/p&&p&&br&&/p&&h2&遮蔽物&/h2&&p&有时“鸡贼”点,适当设计一些遮蔽物是比较理想的做法,无论是优化纹理,还是为了减少工作量。&/p&&p&我们有一个车造型的Boss,想给他设计一个在镜头前漂移着呼啸而过的出场动画。&/p&&p&基本过程设想是下图这样:&/p&&figure&&img src=&https://pic1.zhimg.com/v2-d34b0ac1c218_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&512& data-rawheight=&520& class=&origin_image zh-lightbox-thumb& width=&512& data-original=&https://pic1.zhimg.com/v2-d34b0ac1c218_r.jpg&&&/figure&&p&车尾在镜头前漂移驶过,而后再加速向前方驶去,在最后时再来一个慢镜头特写,配合Boss名字砸在屏幕上,欧耶,完美!(这得画到什么时候(╯-_-)╯╧╧ )&/p&&p&&br&&/p&&p&用2D帧动画的话,从①到③的过程需要很多帧,得画尿血,3转2最后也会是一张超大Atlas。后来我们讨论了一下,决定做的“偷”一点,使用了如下方案——加入遮蔽烟雾。&/p&&figure&&img src=&https://pic2.zhimg.com/v2-38d36f0b6bebe647f9eef6b_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&512& data-rawheight=&241& data-thumbnail=&https://pic4.zhimg.com/v2-38d36f0b6bebe647f9eef6b_b.jpg& class=&origin_image zh-lightbox-thumb& width=&512& data-original=&https://pic4.zhimg.com/v2-38d36f0b6bebe647f9eef6b_r.jpg&&&/figure&&p&车尾在屏幕右侧进场,在镜头前滑过,这整个过程车子只有位移和缩放,没有任何透视的变化。但由于大部分画面车子都有烟雾的帧动画进行遮挡,配合上位移和镜头的晃动,车子最后的”慢镜效果“是使用Free Form Deformation,整体看上去是不是有了3D的景深和立体感?&/p&&p&换了没有烟雾的效果再看下:&/p&&figure&&img src=&https://pic1.zhimg.com/v2-4d0e66dedac_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&512& data-rawheight=&237& data-thumbnail=&https://pic1.zhimg.com/v2-4d0e66dedac_b.jpg& class=&origin_image zh-lightbox-thumb& width=&512& data-original=&https://pic1.zhimg.com/v2-4d0e66dedac_r.jpg&&&/figure&&p&遮蔽物的使用原则是——用小的素材进行动画去遮蔽大的素材,或是用简单的动画去遮蔽一个复杂的动画。此处烟雾的应用减少了关键帧,营造了“漂过的似乎车子真的有透视变化”的效果,并且烟雾还有一个关键作用,就是作为“遮眼法”,过渡了“漂移的大车”这一帧替换“向前驶去的小车”帧的镜头,观众会根据前摇和后摇的运动轨迹去脑补被遮蔽的中间的过程。(看到车子先向左划过的前摇,和冲出去的后摇,把没看到的过程自动脑补成S弯,其实就是平移和缩放。)&/p&&p&&br&&/p&&h2&&b&混合使用位移和部件关键帧&/b&&/h2&&p&仅关键部件使用不同透视的纹理而其余部件仅采用位移,有时能产生“似乎整体都有透视变化”的错觉。&/p&&figure&&img src=&https://pic4.zhimg.com/v2-5d68ce1e53e89f2ec5990_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&226& data-rawheight=&280& data-thumbnail=&https://pic1.zhimg.com/v2-5d68ce1e53e89f2ec5990_b.jpg& class=&content_image& width=&226&&&/figure&&p&&br&&/p&&p&图中机甲的移动只有大腿和膝盖两个关键部件拥有不同透视的帧动画,其余部件仅仅使用位移,让观众觉得似乎小腿、脚、胸部和头似乎都有一些透视上的变化。用这种要注意动作符合运动规律,被遮挡的部件可以大幅移动(脚和小腿),较大的和暴露在最顶的层部件不适合做过大幅度动作(胸口和头),毕竟它们没有透视变化,大位移容易穿帮。&/p&&p&这部分内容,日系的2D游戏提供了很多范例,就不献丑了。&/p&&p&&br&&/p&&h2&&b&使用3D技术辅助&/b&&/h2&&p&想要3D的感觉最简单的方式就是直接用3D(废话…(⊙_⊙;)… )。这部分无需多言,一些透视要画准的话是2D,必要时也需要一些3D的工具的辅助,比如草图大师,甚至是建模。&/p&&figure&&img src=&https://pic4.zhimg.com/v2-680c3c52422accb72b168b40c8ac3a6f_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&400& data-rawheight=&878& class=&content_image& width=&400&&&/figure&&p&2D做出3D感其实就是用2D的素材来模拟3D世界的运动规律,但2D游戏毕竟是2D的纹理,想要百分百的3D效果那说明使用3D来制作游戏是最经济的。2D只是用技巧制造一些视觉表现力,达到欺骗眼睛的效果就够了。&/p&&p&&br&&/p&&p&最后,丢个过场动画的GIF,使用2D素材和Free Form Deformation实现。 &/p&&figure&&img src=&https://pic1.zhimg.com/v2-e4d3c32aedc9d573e6101d_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&512& data-rawheight=&288& data-thumbnail=&https://pic2.zhimg.com/v2-e4d3c32aedc9d573e6101d_b.jpg& class=&origin_image zh-lightbox-thumb& width=&512& data-original=&https://pic2.zhimg.com/v2-e4d3c32aedc9d573e6101d_r.jpg&&&/figure&&p&&/p&
这是我之前在cowlevel中写的一篇回答。这个专栏刚刚开辟,内容少的惨不忍睹,所以搬运了过来。在开发过程当中有一些有意思的事情比较值得记录,后面有时间的时候,我会慢慢整理出来。这里先提前挖个坑。cowlevel的提问是“
&figure&&img src=&https://pic2.zhimg.com/v2-d44ad723e1a3db9843ae01_b.jpg& data-rawwidth=&550& data-rawheight=&299& class=&origin_image zh-lightbox-thumb& width=&550& data-original=&https://pic2.zhimg.com/v2-d44ad723e1a3db9843ae01_r.jpg&&&/figure&&h2&&b&PART 1 准备工作&/b&&/h2&&p&&b&关于PMI,PMP 与 PMBOK&/b&&/p&&p&PMP ( Project Management Professional ) 指项目管理专业人士,PMP 资格认证考试由美国项目管理协会(PMI)举办,是目前项目管理领域含金量最高的认证。PMI 早在二十世纪七十年代末就率先提出了项目管理的知识体系(Project Management Body of Knowledge,简称为 PMBOK)。PMBOK 第一版于 1996 年问世,由 200 多名世界各国的项目管理专家历经四年才完成。每隔数年,来自世界各地的项目管理专家会重新审查更新 PMBOK 的内容,使它始终保持最权威的地位。PMBOK 至今已修订至第五版。&/p&&figure&&img src=&https://pic2.zhimg.com/v2-9f1405cfe68f4dabdc39_b.jpg& data-rawwidth=&510& data-rawheight=&546& class=&origin_image zh-lightbox-thumb& width=&510& data-original=&https://pic2.zhimg.com/v2-9f1405cfe68f4dabdc39_r.jpg&&&/figure&&p&PMBOK是项目管理领域最权威的知识体系指南,也是PMP资格认证考试的基础。可是将近600页的厚度着实很打击人的学习积极性,对于不想考证只想了解项目管理知识体系的小伙伴们来说,也不需要读得那么仔细。于是小编为大家整理了一个15分钟简易版,供大家快速学习PMBOK。&/p&&br&&p&&b&PMBOK的特点&/b&&/p&&p&PMBOK并不是项目管理方面的万能书,在学习之前我们了解PMBOK的特点:&/p&&p&-
PMBOK收录了项目管理知识体系中&b&被普遍认可为良好做法&/b&的那一部分,大多时候适用于大多项目&/p&&p&-
只针对&b&通用的项目管理知识&/b&,&b&不针对任何具体行业&/b&&/p&&p&-
只针对单一项目管理,不针对项目集和项目组合&/p&&p&-
&b&是一份指南,不是具体的方法论&/b&&/p&&br&&p&&b&几个重要的基本概念&/b&&/p&&p&在开始快速学习前,我们先了解几个重要的基本概念。&/p&&br&&p&&u&1. 什么是项目?&/u&&/p&&p&PMBOK中把项目定义为“为了创造独特的产品、服务或成果而进行的临时性工作”。&/p&&p&项目有三大特点:临时性,独特性,渐进明细性。“渐进明细性”可解释为项目目标从方向性大目标到可测量的小目标,产品范围和项目范围从粗略到详细,项目计划从控制性计划到具体操作。简言之,就是随着项目的开展,项目的目标、范围、计划等慢慢变得细致明确。&/p&&p&另外,注意把项目与运营区分开来。项目需要有明确的开始时间和结束时间,即项目的临时性。如果是常规的重复的持续不断的工作,则属于运营工作的范畴,比如举办亚运会。&/p&&br&&p&&u&2.什么是项目干系人?&/u&&/p&&p&项目干系人是指能影响项目决策,活动或结果的个人,群体或组织,以及会受或自认为会受项目决策,活动或结果影响的,个人,群体或组织。简言之,就是会影响项目,以及会受到项目(潜在)影响的人群。&/p&&figure&&img src=&https://pic3.zhimg.com/v2-e48ac0ef46f636d430dcfae2108cfb62_b.jpg& data-rawwidth=&1405& data-rawheight=&724& class=&origin_image zh-lightbox-thumb& width=&1405& data-original=&https://pic3.zhimg.com/v2-e48ac0ef46f636d430dcfae2108cfb62_r.jpg&&&/figure&&p&PMBOK&b&强调了干系人管理的重要性&/b&。因为干系人之间不同的期望或利益会在项目中引发冲突,可能对项目造成消极影响;且不同干系人对项目的影响和责任是随着项目生命周期进展而变化的,这就要求项目经理对干系人作出持续性的管理。PMBOK定义项目经理的重要职责之一为:&b&管理项目干系人的期望+平衡干系人的不同利益。&/b&&/p&&br&&p&&u&3.什么是组织过程资产?&/u&&/p&&p&组织过程资产是执行组织所特有并使用的计划、流程、政策、程序和知识库,可能还包括完整的进度计划、风险数据和挣值数据。组织过程资产可分成两大类:流程与程序,共享知识库(经验教训和历史信息)。&/p&&p&在项目全过程中,项目团队成员通常有责任对组织过程资产进行&b&持续的更新和增补&/b&。组织过程资产是大部分规划过程的输入。&/p&&br&&p&&u&4.什么是事业环境因素?&/u&&/p&&p&事业环境因素是指项目团队&b&不能控制的&/b&,&b&将对项目产生影响、限制或指令作用的各种条件&/b&,可能提高或限制项目管理的灵活性,并可能对项目结果产生积极或消极的影响。&/p&&p&从性质或类型上讲,事业环境因素是多种多样的,包括(但不限于): 组织文化、政府或行业标准、基础设施、现有人力资源状况、人事管理制度、市场条件、商业数据库和项目管理信息系统等。事业环境因素也是大多数规划过程的输入。&/p&&br&&p&&b&一张图总结PMBOK所有知识点&/b&&/p&&p&项目管理过程包含五大项目管理过程组和十大项目管理知识领域。&/p&&p&五大项目管理过程组:启动,规划,执行,监控,收尾。&/p&&p&十大项目管理知识领域:整合管理,范围管理,时间管理,成本管理,质量管理,人力资源管理,沟通管理,风险管理,采购管理,干系人管理。&/p&&p&熟悉了这个框架, 心中就有了PMBOK!&/p&&figure&&img src=&https://pic4.zhimg.com/v2-999a724b0afa919f2c9f_b.jpg& data-rawwidth=&1186& data-rawheight=&1567& class=&origin_image zh-lightbox-thumb& width=&1186& data-original=&https://pic4.zhimg.com/v2-999a724b0afa919f2c9f_r.jpg&&&/figure&&h2&&b&PART 2 五大项目管理过程组简析&/b&&/h2&&br&&p&下面我们来简单看下五大过程组的关系,以及每个过程组里分别要做什么,重点是什么。&/p&&p&&b&五大过程组的关系&/b&&/p&&p&启动,规划,监控,执行,收尾这五大过程组构成了项目管理生命周期,他们之间有清晰的,相互依赖与相互作用关系。在项目完成之前,往往需要&b&反复实施&/b&各过程组及其过程。&/p&&p&值得注意的是,&b&规划过程组&/b&和&b&执行过程组&/b&是相互影响相互作用的,而&b&监控过程组&/b&贯穿了整个项目管理生命周期。&/p&&figure&&img src=&https://pic1.zhimg.com/v2-ce5b1eea8e83d7fd0cdc_b.jpg& data-rawwidth=&640& data-rawheight=&312& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&https://pic1.zhimg.com/v2-ce5b1eea8e83d7fd0cdc_r.jpg&&&/figure&&p&&b&启动过程组(Initiating Process Group)需要做些什么?&/b&&/p&&p&&i&关键词:定义初步范围(项目边界),授权项目开始,识别内外部干系人,选定项目经理。&/i&&/p&&p&&b&- 制定项目章程&/b&:一般由项目发起人起草,正式授权项目,任命项目经理,定义初步的项目范围(项目边界),落实初步的财务资源。&/p&&p&&b&- 识别干系人&/b&:识别干系人,并分析和记录他们的相关信息的过程。这些信息包括他们的利益、参与度、相互依赖、影响力及对项目成功的潜在影响等。过程的主要作用是,帮助项目经理建立对各个干系人或干系人群体的适度关注。&/p&&figure&&img src=&https://pic1.zhimg.com/v2-c5b3e6cd9a_b.jpg& data-rawwidth=&1490& data-rawheight=&711& class=&origin_image zh-lightbox-thumb& width=&1490& data-original=&https://pic1.zhimg.com/v2-c5b3e6cd9a_r.jpg&&&/figure&&br&&p&&b&规划过程组(Planning Process Group)需要做些什么?&/b&&/p&&p&&i&关键词:反复进行,滚动式规划;明确项目范围,为实现项目目标制定行动方案(即制定项目管理计划)。&/i&&/p&&p&&b&- 项目范围管理领域:规划范围管理---&收集需求---&定义范围---&创建WBS&/b&&/p&&p&这里重点说一下WBS。WBS(Work Breakdown Structure)工作分解结构,是对全部工作范围的一个层级分解。创建WBS,是把项目可交付成功和项目工作分解成&b&较小的,更易于管理的组件&/b&的过程&/p&&p&主要是为了对所要交付的内容提供一个结构化的视图,输出项目的&b&范围基准&/b&。&/p&&figure&&img src=&https://pic4.zhimg.com/v2-eb00bf735e25b9f2555e77_b.jpg& data-rawwidth=&1334& data-rawheight=&813& class=&origin_image zh-lightbox-thumb& width=&1334& data-original=&https://pic4.zhimg.com/v2-eb00bf735e25b9f2555e77_r.jpg&&&/figure&&br&&p&如果没有WBS,就无法制定进度,成本,风险和人员计划等。编制WBS不仅是其他项目规划工作的基础,也是整个项目实施的基础。分解规则遵循100%分解原则,即包含所有项目工作,不多也不少,且以可交付成果为导向。&/p&&p&&b&- 项目时间管理领域:规划进度管理---&定义活动---&排列活动顺序----&估算活动资源---&估算活动持续时间---&制定进度计划&/b&&br&&br&&/p&&p&项目进度计划一般用三种图来表示:里程碑图,横道图(甘特图),项目进度网络图(如下)。制定进度计划用到的主要方法是:关键路径法和关键链法,以及资源优化技术。关键路径是进度计划中总工期最长的那条路径,决定这项目完工的最短工期。&/p&&figure&&img src=&https://pic1.zhimg.com/v2-1ec7d86dfd5e6a04afc134_b.jpg& data-rawwidth=&1409& data-rawheight=&1133& class=&origin_image zh-lightbox-thumb& width=&1409& data-original=&https://pic1.zhimg.com/v2-1ec7d86dfd5e6a04afc134_r.jpg&&&/figure&&p&&b&- 项目成本管理领域:规划成本管理----&估算成本---&制定预算&/b&&/p&&p&估算成本的常用方法有:专家判断,类比估算,参数估算,三点估算,除非分析,自下而上估算,质量成本,储备分析等。自下而上的估算需要参照上面提到的WBS;储备分析需要在项目预算中设置应急储备和管理储备来应对风险事件。&/p&&figure&&img src=&https://pic3.zhimg.com/v2-add73a87ea_b.jpg& data-rawwidth=&1381& data-rawheight=&749& class=&origin_image zh-lightbox-thumb& width=&1381& data-original=&https://pic3.zhimg.com/v2-add73a87ea_r.jpg&&&/figure&&p&&b&- 项目风险管理领域:规划风险管理---&识别风险----&实施定性风险分析---&实施定量风险分析---&规划风险应对&/b&&br&&/p&&p&识别风险过程结束后,会输出风险登记册,用来记录与追踪所有风险。随着项目的进展,风险等级侧会不断更新。定性风险分析是评估已识别风险的概率和影响,对风险进行优先级排序,并重点关注高优先级的风险。定量风险分析是分析重大风险对项目整体目标影响的程度,需要借助建模技术。&/p&&p&&b&- 项目其他领域:规划质量管理,规划人力资源管理,规划沟通管理,规划人力资源管理,规划采购管理,规划干系人管理&/b&。&/p&&p&总结:项目的规划过程组就是规划各个领域的管理计划, 综合成一份总的“项目管理计划”,包括所有子管理计划和三项基准(范围基准,时间基准,成本基准)&/p&&p&&b&执行过程组(Executing Process Group)需要做些什么?&/b&&/p&&p&&i&关键词:执行计划,并产生可交付成果;引发变更请求,并执行经过批准的变更;更新项目管理计划或建立新的基准。&/i&&/p&&p&- &b&项目人力资源管理领域:&/b&组建项目团队---&建设项目团队---&管理项目团队;&/p&&p&在管理项目团队部分,重点是管理冲突。PMI任务合理的冲突是有益的,只要有界面,冲突不可避免&/p&&p&冲突的来源主要是:资源稀缺与优先级顺序。推崇用合作/解决(collaborate / Problem Solve)来解决冲突。冲突当事人采用合作的态度以及开放式对话达成共识和承诺。紧急情况下需要使用强制/命令(Force/Direct)的方式解决冲突,以免错过时机,拖延而影响项目。&/p&&p&&b&- 项目干系人管理领域:管理干系人参与&/b&&/p&&p&管理干系人参与是在整个项目生命周期中,与干系人进行沟通和协作,以满足其需要与&/p&&p&期望,解决实际出现的问题,并促进干系人合理参与项目活动的过程。管理干系人参与的主要作用是&/p&&p&帮助项目经理&b&提升来自干系人的支持&/b&,并&b&把干系人的抵制降到最低&/b&,从而&b&显著提高&/b&项目成功&/p&&p&的机会。&/p&&p&&b&- 项目质量管理领域:实施质量保证&/b&&/p&&p&实施质量保证主要是为了确保采用合理的质量标准和操作定义,以及促进质量过程改进,有常用的7种质量管理和控制工具。&/p&&figure&&img src=&https://pic4.zhimg.com/v2-71ba809dacc138a7e039a3_b.jpg& data-rawwidth=&1394& data-rawheight=&1077& class=&origin_image zh-lightbox-thumb& width=&1394& data-original=&https://pic4.zhimg.com/v2-71ba809dacc138a7e039a3_r.jpg&&&/figure&&p&&b&- 项目采购管理领域:实施采购&/b&&/p&&p&实施采购是获取卖方应答、选择卖方并授予合同的过程。这个过程的主要作用是,通过达&/p&&p&成协议,使内部和外部干系人的期望协调一致。&/p&&p&&b&- 项目沟通管理领域:管理沟通&/b&&/p&&p&管理沟通是根据沟通管理计划,生成、收集、分发、储存、检索及最终处置项目信息的&/p&&p&过程。这个过程的主要作用是,促进项目干系人之间实现&b&有效率且有效果&/b&的沟通。&/p&&p&&b&监控过程组(Monitoring and Controlling Process Group)需要做些什么?&/b&&/p&&p&&i&关键词:跟踪项目绩效,识别与项目管理计划的偏差;识别必要的变更,并启动相应变更程序。&/i&&/p&&p&&b&- 项目范围管理领域:确认范围--&控制范围&/b&&/p&&p&确认范围是指客户或发起人正式验收可交付成果;控制范围是指在整个项目期间保持对范围基准的维护,监控,管理范围变更。&/p&&br&&p&&b&- 其他领域:控制进度,控制成本,控制质量,控制采购,控制沟通,控制风险,控制采购。&/b&&/p&&p&控制成本中一个重要的概念叫挣值管理(EVM),即在既定的范围下追求进度和成本绩效的综合最优。EV表示实际完成工作量的预算价值,PV表示计划完成工作量的预算价值,AC表示标识实际完成工作量的成本。用这三个值来综合衡量项目绩效,并对未来的项目绩效做出预测。&/p&&figure&&img src=&https://pic1.zhimg.com/v2-15f193a607b493f7d2a236afc48f5ac4_b.jpg& data-rawwidth=&1404& data-rawheight=&758& class=&origin_image zh-lightbox-thumb& width=&1404& data-original=&https://pic1.zhimg.com/v2-15f193a607b493f7d2a236afc48f5ac4_r.jpg&&&/figure&&p&控制质量主要是关注可交付成果是否正确以及是否满足质量要求,比较注重正确性。&/p&&p&关于可交付成果从产生到最终被客户验收,会经历这样的过程:执行过程组--&可交付成果--&&b&控制质量&/b&--&核实的可交付成果--&&b&确认范围&/b&--&验收的可交付成果。&/p&&p&控制沟通的主要作用是,在整个项目生命周期中确保所有沟通参与者之间的信息流动的最优化。&/p&&p&控制风险是在整个项目中实施风险应对计划、跟踪已识别风险、监督残余风险、识别新风险,以及评估风险过程有效性的过程。&/p&&p&&b&收尾过程组(Closing Process Group)需要做些什么?&/b&&/p&&p&&i&关键词:正式结束项目或阶段或合同责任,结束采购。&/i&&/p&&p&另外,收尾过程组也用于正式处理项目提前结束的情形。提前结束的项目可能包括:中止的项目、取消的项目或有严重问题的项目。在特定情况下,如果合同无法正式关闭(因索赔、终止条款等原因),或者需要向其他部门转移某些活动,可能需要安排和落实具体的交接手续。&/p&&p&&b&收尾过程组可能需要进行以下活动:&/b&&/p&&p&- 进行项目后评价或阶段结束评价;&/p&&p&- 记录经验教训;&/p&&p&- 对组织过程资产进行适当更新;&/p&&p&- 将所有相关项目文件在项目管理信息系统中归档,以便作为历史数据使用;&/p&&p&- 结束所有采购活动,确保所有相关协议的完结;&/p&&p&- 对团队成员进行评估,释放项目资源。&/p&&p&&b&PART 3 整体变更控制&/b&&/p&&p&变更是项目进行中不可避免的问题,项目中的许多纠纷都是由变更管理不当造成的。PM需要有很强的变更控制能力,即&b&对可能引起变更的因素施加影响,同时对导致规避整体变更控制的因素施加影响。&/b&&/p&&p&&b&PMP特别强调了所有变更都需要进行整体变更控制,&/b&涉及到修改基准的变更需要提交“变更控制委员会”(正式团队,由主要干系人组成)&b&。&/b&PM需要尽量防止不必要的变更,一旦变更出现,必须严格执行整体变更控制过程。&/p&&p&&b&整体变更控制的过程大致如下:&/b&&/p&&p&提出变更,书面记录---&评价变更对所在领域的影响---&评价变更对项目的综合影响---&设计变更备选方案---&与干系人会谈---&批准,否决,或悬置变更---&更新项目计划或项目文件---&通知受变更影响的干系人---&追踪变更实施情况---&总结经验教训。&/p&&br&&p&&i&&b&更多干货请关注码市公众号:Coding码市&/b&&/i&&/p&
PART 1 准备工作关于PMI,PMP 与 PMBOKPMP ( Project Management Professional ) 指项目管理专业人士,PMP 资格认证考试由美国项目管理协会(PMI)举办,是目前项目管理领域含金量最高的认证。PMI 早在二十世纪七十年代末就率先提出了项目管理的知识体系(P…
&p&岂止是有潜力,简直是很合适!&/p&&p&猪厂两大游戏客户端引擎,NeoX 和 Messiah,都使用 Python 作为脚本语言。&/p&&p&你最近所了解的比较火的挂着猪厂旗号的,也都是 Python 写的。&/p&&figure&&img src=&https://pic1.zhimg.com/v2-9bc667aec9a4_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&266& data-rawheight=&312& class=&content_image& width=&266&&&/figure&&p&一些项目组甚至不需要分出人力去维护引擎部分,因为引擎本身比较稳。&/p&&p&也就是说,程序绝大部分时间都可以专注用 Python 写逻辑,保持创造力。&/p&&figure&&img src=&https://pic3.zhimg.com/v2-682bd66db392_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&235& data-rawheight=&251& class=&content_image& width=&235&&&/figure&&p&还有就是 Python 写各种工具,编辑器,不是一般的爽。PyQt 在手天下我有。&/p&&p&还能和项目代码无缝衔接。&/p&&p&————————&/p&&p&&b&服务端:&/b&&/p&&p&也是纯 Python。&/p&&p&因此很多代码可以服务端客户端共用,尤其是数据结构定义,序列化等。&/p&&p&用过的才知道前后端用同一种语言有多方便。&/p&&p&同一套 Excel 配表,用 Python 写的工具转成 py 文件,然后服务端和客户端都用这个。&/p&&p&同一个类,服务端用,客户端也用,还需要啥数据格式转换啊(滑稽)。&/p&&p&————————&/p&&p&&b&效率问题:&/b&&/p&&p&运行效率大部分情况下都不是问题,开发效率却可以提升几个数量级。&/p&&p&————————&/p&&p&&b&静态类型语言 vs 动态类型语言:&/b&&/p&&p&这是个有争议的话题。&/p&&p&个人看法这是一种 trade-off,牺牲逻辑的严谨性,以及架构,来换取开发效率。&/p&&p&这样做当然很多弊端,只是在目前这个阶段,开发效率比什么都重要,真的。&/p&&p&&i&(项目组都要解散了你跟我说你的代码更好看?)&/i&&/p&&p&————————&/p&&p&&b&多线程:&/b&&/p&&p&客户端逻辑没有必要。&/p&&p&游戏项目从来都不是计算密集型的,逻辑本来就够复杂了,多线程会进一步增加复杂度,得不偿失。&/p&&p&&i&(一般情况下不需要,要用的话祝你好运)&/i&&/p&&p&————————&/p&&p&&b&Hotfix:&/b&&/p&&p&网络游戏正在逐渐成为一种服务,成为每个人的日常娱乐方式。&/p&&p&服务的稳定也变得越来越重要,如果隔三差五就得停服修bug,客户端动不动就得整包更新,会严重影响玩家体验。&/p&&p&而用 Python 进行热更是语言原生支持的,意味着实现成本很低,风险低,操作也很方便。&/p&&p&————————&/p&&p&&b&最后的废话:&/b&&/p&&p&不要想当然,不要听风就是雨,实践出真知。&/p&
岂止是有潜力,简直是很合适!猪厂两大游戏客户端引擎,NeoX 和 Messiah,都使用 Python 作为脚本语言。你最近所了解的比较火的挂着猪厂旗号的,也都是 Python 写的。一些项目组甚至不需要分出人力去维护引擎部分,因为引擎本身比较稳。也就是说,程序绝大…
&h2&第一步:明确目的&/h2&&p&年终总结不是流水账,不是应付差事,千万要摆正心态,认真对待。一般来说,如果你是某个产品负责人,你的汇报对象是公司中、高层,那你的总结应至少满足以下目的:&/p&&ul&&li&复盘产品发展路径:让大家知道,这一年你负责的产品的迭代情况,每次迭代上线的功能,以及满足了用户哪些场景的需求。&/li&&li&总结具体工作内容:让大家知道,你作为产品经理,在职责范围内都做了哪些事?&/li&&li&工作亮点的挖掘、曝光:让大家知道,你做了哪些能体现你价值的事情,尤其是做了哪些事情?为公司创造了哪些价值?从而为你的职级晋升做背书。&/li&&li&工作不足的反思、改进:人无完人,也需要让大家知道这一年下来,还有哪些需要提高的点,以及针对这些问题的解决方案。&/li&&li&下一年的计划和预期结果:让大家知道,你根据公司战略规划,对产品未来一年的发展有哪些计划?预计要做哪些事?&/li&&/ul&&h2&第二步:列提纲&/h2&&p&以个人经验,一份年终总结可分以下几个维度撰写:&/p&&ol&&li&时间维度上,产品里程碑节点罗列&/li&&li&数据维度上,核心数据变化趋势&/li&&li&任务维度上,按项目模块说明产品任务执行情况&/li&&li&任务维度上,说明非产品任务的执行情况&/li&&li&说明工作亮点,辅助以数据证明&/li&&li&说明工作不足,及改进方案&/li&&li&管理维度上(如果有),团队建设情况说明&/li&&li&产品未来发展规划&/li&&/ol&&h2&第三步:填内容&/h2&&p&针对以上几个维度,举例详细展开&/p&&h3&1、时间维度上,产品里程碑节点罗列&/h3&&p&主要就是以产品上线时间为横轴,展示一年内App的发版节点,以及每个版本支持的功能,如果某个版本属于里程碑级的,则需重点标明。如下图:&/p&&h3&2、数据维度上,核心数据变化趋势&/h3&&p&数据说话,说明产品的市场表现,尤其是今年和去年的对比。向领导级汇报,可呈现真实数据,否则可以百分比代替,或仅展示曲线变化趋势。App重点数据维度包括:装机量、活跃用户数、留存率、AppStore排名评星等。如下图:&/p&&h3&3、任务维度上,按项目模块说明产品任务执行情况&/h3&&p&这一点就因人而异,因产品而异了。如果你一人负责整个App,则要拆解每个大模块分别说明。如果你负责某个子模块,针对这个模块做详细说明即可。说明的要点包括:模块更新次数、每次更新时间、每次更新功能、功能上线目的、功能上线结果这几点,如果有数据能佐证则一定要加上。如下图:&/p&&h3&4、任务维度上,说明非产品任务的执行情况&/h3&&p&除了产品经理常规的原型设计、需求分析、项目管理、部门沟通外,优秀的产品经理还会做很多“非常规”工作,包括了解市场、知识分享、效率提升、用户访谈等。如果有,则可作为工作加成说出来。如下图:&/p&&h3&5、说明工作亮点,辅助以数据证明&/h3&&p&如果你设计的某个功能模块,或你主导的某个运营活动,对新增、活跃、品牌传播做出很大贡献,就一定要单独列出,尤其要提供数据证明。如果是后台产品,则可改为提升多少工作效率。&/p&&h3&6、说明工作不足,及改进方案&/h3&&p&包括工作失误、进度延误、沟通不足、用户反馈问题等,都可以写。也可反思自己是否还存在提升空间,能否把60分工作提升到90分,并讲出切实可行的方法。如图:&/p&&h3&7、管理维度上(如果有),团队建设情况说明&/h3&&p&如果你是管理岗,就有带团队的任务,那团队这一年的成长情况也是你需要总结汇报的。包括人力情况,多少人入职、多少人离职、多少人转正、多少人晋升。以及团队建设情况,是否有举办过团队培训、团队出游、团队分享等活动。例如:&/p&&h3&8、产品未来发展规划&/h3&&p&最后,针对你负责的产品,需要根据公司战略规划,写出你对产品功能、用户体验、模块划分、数据提升方面的想法,可分模块整理,做粗略总结。&/p&&h2&第四步:查漏补缺,注意细节&/h2&&p&写好的年终总结,务必要仔细检查,如需开会汇报,还要提前演练,控制时间。以下是几个需要注意的点,我给归类成“三要三忌”。&/p&&p&“三要”:&/p&&ol&&li&要强调成果,并给出合理的达成原因&/li&&li&要反思问题,并给出可行的改进方案&/li&&li&要注意排版&/li&&/ol&&p&“三忌”:&/p&&ol&&li&切忌流水账,要主次分明,突出重点即可,尤其强调成果。&/li&&li&切忌自说自话,要让数据说话,好就是好,不好就是不好&/li&&li&切忌不切实际的计划,如不确定最好先和领导沟通&/li&&/ol&&p&以上就是根据经验整理的产品经理年终总结撰写指南,供读者参考~&/p&
第一步:明确目的年终总结不是流水账,不是应付差事,千万要摆正心态,认真对待。一般来说,如果你是某个产品负责人,你的汇报对象是公司中、高层,那你的总结应至少满足以下目的:复盘产品发展路径:让大家知道,这一年你负责的产品的迭代情况,每次迭代上…
&p&大致有以下几种方法:&br&&br&&br&差异化关键帧。&br&比如起跳,起跳的预备动作用3帧,从离地的一帧,到十米开外只用一帧。这样几乎看不到加速度,像是瞬间把速度提高到了10米每秒,又瞬间停止。跑步的话可以把运行时间调短,减少帧数。这样会显得不流畅但会有速度感。是格斗游戏其中比较常见的方法。&br&&br&&br&&br&扩大视角(field of view)&br&赛车游戏的时候我们尝尝看到地面和周围的景物变成竖线,其实就是把视角增大,把扩大面积的视觉效果挤在原有的矩形窗口内就会产生这样的竖线。是比较常见好用的方法。&br&&br&拉近镜头,缩小物体:&br&这样如果镜头拉远就看到所有物体都是缓慢移动,就像你看天上飞机觉得飞的很慢一样。但是拉近之后周边景物会快速变化。一样的速度,因为周边景物的快速变化而显得很快。&br&&br&这是普通的视角&br&&/p&&a class=&video-box& href=&//link.zhihu.com/?target=https%3A//www.zhihu.com/video/205824& target=&_blank& data-video-id=&& data-video-playable=&& data-name=&& data-poster=&https://pic3.zhimg.com/v2-2aa1fbfb11b80e25f6be59af.jpg& data-lens-id=&205824&&
&img class=&thumbnail& src=&https://pic3.zhimg.com/v2-2aa1fbfb11b80e25f6be59af.jpg&&&span class=&content&&
&span class=&title&&&span class=&z-ico-extern-gray&&&/span&&span class=&z-ico-extern-blue&&&/span&&/span&
&span class=&url&&&span class=&z-ico-video&&&/span&https://www.zhihu.com/video/205824&/span&
&/a&&br&这是拉近视点&a class=&video-box& href=&//link.zhihu.com/?target=https%3A//www.zhihu.com/video/557376& target=&_blank& data-video-id=&& data-video-playable=&& data-name=&& data-poster=&https://pic4.zhimg.com/v2-1aab7acaab01cbd4b7820089.jpg& data-lens-id=&557376&&
&img class=&thumbnail& src=&https://pic4.zhimg.com/v2-1aab7acaab01cbd4b7820089.jpg&&&span class=&content&&
&span class=&title&&&span class=&z-ico-extern-gray&&&/span&&span class=&z-ico-extern-blue&&&/span&&/span&
&span class=&url&&&span class=&z-ico-video&&&/span&https://www.zhihu.com/video/557376&/span&
&/a&这是拉近视点+扩大视角&a class=&video-box& href=&//link.zhihu.com/?target=https%3A//www.zhihu.com/video/860736& target=&_blank& data-video-id=&& data-video-playable=&& data-name=&& data-poster=&https://pic3.zhimg.com/v2-bebffdd2eb.jpg& data-lens-id=&860736&&
&img class=&thumbnail& src=&https://pic3.zhimg.com/v2-bebffdd2eb.jpg&&&span class=&content&&
&span class=&title&&&span class=&z-ico-extern-gray&&&/span&&span class=&z-ico-extern-blue&&&/span&&/span&
&span class=&url&&&span class=&z-ico-video&&&/span&https://www.zhihu.com/video/860736&/span&
&/a&这是扩大视角的一个极端例子,下面这个视频根本没有移动,但产生了强烈的视觉冲击。&a class=&video-box& href=&//link.zhihu.com/?target=https%3A//www.zhihu.com/video/299968& target=&_blank& data-video-id=&& data-video-playable=&& data-name=&& data-poster=&https://pic1.zhimg.com/v2-ffc53f7ce5929d6fcb11c2b.jpg& data-lens-id=&299968&&
&img class=&thumbnail& src=&https://pic1.zhimg.com/v2-ffc53f7ce5929d6fcb11c2b.jpg&&&span class=&content&&
&span class=&title&&&span class=&z-ico-extern-gray&&&/span&&span class=&z-ico-extern-blue&&&/span&&/span&
&span class=&url&&&span class=&z-ico-video&&&/span&https://www.zhihu.com/video/299968&/span&
&/a&如果不想人物变形可以只对天空,地面,或者景物改变视角。但是主意要不能太过变形,或者变形后记得重新调整一下各个组件的位置。特别注意水面和地面必须同时改变视角,因为这两个组件是贴在一起的,天空的话是天空盒子,和地面没有接触所以可以不用一起变。&p&&br&直接增加速度:&br&这个是最为直接的,本来原来1个frame 移动1个单位长,现在一个frame移动10个单位长。一个非常简单粗暴的方法。&br&但是目前所有游戏都会有最高限速。如果一个物体宽是10米,人物速度是100米每frame。这样会出现两种bug,一种是速度太快导致直接穿过物体,还有一种就是速度太快两个物体穿模或者卡住。所以一般游戏速度都不会有10倍的移动速度差异。&br&&br&滤镜处理:&br&也是完全不影响游戏功能,在移动速度高的时候做模糊效果,窗口上贴点加速的线等等,在投射到窗口之间先让滤镜程序接受图片,进行渲染,再传给窗口显示给用户。比如制作抖动场景。&br&&br&对图像整体滤镜运算速度基本可以控制在θ(n),n是长宽像素乘积。如果是在图像前面盖一张有alpha通道的png或动图运算速度大概会在θ(1)。&br&&br&&br&瞬移VS移动:&br&你如果写过游戏就知道这两者没什么本质区别,移动如果是坐标+1,那么瞬移就是坐标+10。一般游戏都会考虑平衡性移动速度差异都不会很大。如果大多数角色都是1的速度,一个10倍的速度简直就是逆天的存在。大多数游戏追求平衡性,减少bug都不会这么做。&/p&
大致有以下几种方法: 差异化关键帧。 比如起跳,起跳的预备动作用3帧,从离地的一帧,到十米开外只用一帧。这样几乎看不到加速度,像是瞬间把速度提高到了10米每秒,又瞬间停止。跑步的话可以把运行时间调短,减少帧数。这样会显得不流畅但会有速度感。是…
&figure&&img src=&https://pic3.zhimg.com/v2-04e15bbffdfad42e907ffc_b.jpg& data-rawwidth=&897& data-rawheight=&564& class=&origin_image zh-lightbox-thumb& width=&897& data-original=&https://pic3.zhimg.com/v2-04e15bbffdfad42e907ffc_r.jpg&&&/figure&&h2&&b&游戏开发中的ECS 架构概述&/b&&/h2&&p&作者:C.y.&/p&&p&Github:&a href=&http://link.zhihu.com/?target=https%3A//github.com/yangruihan& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&github.com/yangruihan&/span&&span class=&invisible&&&/span&&/a&&/p&&h2&&b&0x00 何为ECS架构&/b&&/h2&&p&&i&&b&ECS&/b&&/i&,即 Entity-Component-System(实体-组件-系统) 的缩写,其模式遵循&a href=&http://link.zhihu.com/?target=https%3A//en.wikipedia.org/wiki/Composition_over_inheritance& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&组合优于继承&/a&原则,游戏内的每一个基本单元都是一个&b&实体&/b&,每个&b&实体&/b&又由一个或多个&b&组件&/b&构成,每个&b&组件&/b&仅仅包含代表其特性的数据(即在组件中没有任何方法),例如:移动相关的组件&code&MoveComponent&/code&包含速度、位置、朝向等属性,一旦一个实体拥有了&code&MoveComponent&/code&组件便可以认为它拥有了移动的能力,&b&系统&/b&便是来处理拥有一个或多个相同&b&组件&/b&的&b&实体&/b&集合的工具,其只拥有行为(即在系统中没有任何数据),在这个例子中,处理移动的&b&系统&/b&仅仅关心拥有移动能力的&b&实体&/b&,它会遍历所有拥有&code&MoveComponent&/code&&b&组件&/b&的&b&实体&/b&,并根据相关的数据(速度、位置、朝向等),更新实体的位置。&/p&&p&&b&实体&/b&与&b&组件&/b&是一个一对多的关系,&b&实体&/b&拥有怎样的能力,完全是取决于其拥有哪些&b&组件&/b&,通过动态添加或删除&b&组件&/b&,可以在(游戏)运行时改变&b&实体&/b&的行为。&/p&&h2&&b&0x01 ECS基本结构&/b&&/h2&&p&一个使用ECS架构开发的游戏基本结构如下图所示:&/p&&p&&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-04e15bbffdfad42e907ffc_b.jpg& data-caption=&& data-rawwidth=&897& data-rawheight=&564& class=&origin_image zh-lightbox-thumb& width=&897& data-original=&https://pic1.zhimg.com/v2-04e15bbffdfad42e907ffc_r.jpg&&&/figure&&p&&br&&/p&&p&先有一个World,它是&b&系统&/b&和&b&实体&/b&的集合,而&b&实体&/b&就是一个ID,这个ID对应了&b&组件&/b&的集合。&b&组件&/b&用来存储游戏状态并且没有任何行为,&b&系统&/b&拥有处理&b&实体&/b&的行为但是没有状态。&/p&&h2&&b&0x02 详解ECS中实体、组件与系统&/b&&/h2&&h2&1. 实体&/h2&&p&实体只是一个概念上的定义,指的是存在你游戏世界中的一个独特物体,是一系列组件的集合。为了方便区分不同的实体,在代码层面上一般用一个ID来进行表示。所有组成这个实体的组件将会被这个ID标记,从而明确哪些组件属于该实体。由于其是一系列组件的集合,因此完全可以在运行时动态地为实体增加一个新的组件或是将组件从实体中移除。比如,玩家实体因为某些原因(可能陷入昏迷)而丧失了移动能力,只需简单地将移动组件从该实体身上移除,便可以达到无法移动的效果了。&/p&&p&&b&样例&/b&:&/p&&ul&&li&Player(Position, Sprite, Velocity, Health)&/li&&li&Enemy(Position, Sprite, Velocity, Health, AI)&/li&&li&Tree(Position, Sprite)&/li&&/ul&&p&&i&注:括号前为实体名,括号内为该实体拥有的组件&/i&&/p&&h2&2. 组件&/h2&&p&一个组件是一堆数据的集合,可以使用C语言中的结构体来进行实现。它没有方法,即不存在任何的行为,只用来存储状态。一个经典的实现是:每一个组件都继承(或实现)同一个基类(或接口),通过这样的方法,我们能够非常方便地在运行时动态添加、识别、移除组件。每一个组件的意义在于描述实体的某一个特性。例如,&code&PositionComponent&/code&(位置组件),其拥有&code&x&/code&、&code&y&/code&两个数据,用来描述实体的位置信息,拥有&code&PositionComponent&/code&的实体便可以说在游戏世界中拥有了一席之地。当组件们单独存在的时候,实际上是没有什么意义的,但是当多个组件通过系统的方式组织在一起,才能发挥出真正的力量。同时,我们还可以用空组件(不含任何数据的组件)对实体进行标记,从而在运行时动态地识别它。如,&code&EnemyComponent&/code&这个组件可以不含有任何数据,拥有该组件的实体被标记为“敌人”。&/p&&p&根据实际开发需求,这里还会存在一种特殊的组件,名为 &b&Singleton Component (单例组件)&/b&,顾名思义,单例组件在一个上下文中有且只有一个。具体在什么情况下使用下文系统一节中会提到。&/p&&p&&b&样例&/b&:&/p&&ul&&li&PositionComponent(x, y)&/li&&li&VelocityComponent(X, y)&/li&&li&HealthComponent(value)&/li&&li&PlayerComponent()&/li&&li&EnemyComponent()&/li&&/ul&&p&&i&注:括号前为组件名,括号内为该组件拥有的数据&/i&&/p&&h2&3. 系统&/h2&&p&理解了实体和组件便会发现,至此还未曾提到过游戏逻辑相关的话题。系统便是ECS架构中用来处理游戏逻辑的部分。何为系统,一个系统就是对拥有一个或多个相同组件的实体集合进行操作的工具,它只有行为,没有状态,即不应该存放任何数据。举个例子,游戏中玩家要操作对应的角色进行移动,由上面两部分可知,角色是一个实体,其拥有位置和速度组件,那么怎么根据实体拥有的速度去刷新其位置呢,&code&MoveSystem&/code&(移动系统)登场,它可以得到所有拥有位置和速度组件的实体集合,遍历这个集合,根据每一个实体拥有的速度值和物理引擎去计算该实体应该所处的位置,并刷新该实体位置组件的值,至此,完成了玩家操控的角色移动了。&/p&&p&注意,我强调了移动系统可以得到&b&所有&/b&拥有位置和速度组件的实体集合,因为一个实体同时拥有位置和速度组件,我们便认为该实体拥有移动的能力,因此移动系统可以去刷新每一个符合要求的实体的位置。这样做的好处在于,当我们玩家操控的角色因为某种原因不能移动时,我们只需要将速度组件从该实体中移除,移动系统就得不到角色的引用了,同样的,如果我们希望游戏场景中的某一个物件动起来,只需要为其添加一个速度组件就万事大吉。&/p&&p&一个系统关心实体拥有哪些组件是由我们决定的,通过一些手段,我们可以在系统中很快地得到对应实体集合。&/p&&p&上文提到的 &b&Singleton Component (单例组件)&/b& ,明白了系统的概念更容易说明,还是玩家操作角色的例子,该实体速度组件的值从何而来,一般情况下是根据玩家的操作输入去赋予对应的数值。这里就设计到一个新组件&code&InputComponent&/code&(输入组件)和一个新系统&code&ChangePlayerVelocitySystem&/code&(改变玩家速度系统),改变玩家速度系统会根据输入组件的值去改变玩家速度,假设还有一个系统&code&FireSystem&/code&(开火系统),它会根据玩家是否输入开火键进行开火操作,那么就有 2 个系统同时依赖输入组件,真实游戏情况可能比这还要复杂,有无数个系统都要依赖于输入组件,同时拥有输入组件的实体在游戏中仅仅需要有一个,每帧去刷新它的值就可以了,这时很容易让人想到单例模式(便捷地访问、只有一个引用),同样的,单例组件也是指整个游戏世界中有且只有一个实体拥有该组件,并且希望各系统能够便捷的访问到它,经过一些处理,在任何系统中都能通过类似&code&world-&GetSingletonInput()&/code&的方法来获得该组件引用。&/p&&p&系统这里比较麻烦,还存在一个常见问题:由于代码逻辑分布于各个系统中,各个系统之间为了解耦又不能互相访问,那么如果有多个系统希望运行同样的逻辑,该如何解决,总不能把代码复制 N 份,放到各个系统之中。&b&UtilityFunction&/b&(实用函数) 便是用来解决这一问题的,它将被多个系统调用的方法单独提取出来,放到统一的地方,各个系统通过 &b&UtilityFunction&/b& 调用想执行的方法,同系统一样, &b&UtilityFunction&/b& 中不能存放状态,它应该是拥有各个方法的纯净集合。&/p&&p&&b&样例&/b&:&/p&&ul&&li&MoveSystem(Position, Velocity)&/li&&li&RenderSystem(Position, Sprite)&/li&&/ul&&p&&i&注:括号前为系统名,括号内为该系统关心的组件集合&/i&&/p&&h2&&b&0x03 ECS架构实战&/b&&/h2&&p&接下来终于到了实战环节,这里笔者使用 Unity3d 游戏引擎(5.6.3p4),配合现成的 &a href=&http://link.zhihu.com/?target=https%3A//github.com/sschmid/Entitas-CSharp& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Entitas&/a& 框架来实现一个小 Demo。由于 Unity3d 游戏引擎已经为我们提供了输入类和物理引擎,因此 Demo 中有部分内容可能与上文不太一致,主要以展示整体架构为主,请读者忽略这些细节。&/p&&h2&1. Entitas介绍&/h2&&blockquote&Entitas is a super fast Entity Component System Framework (ECS) specifically made for C# and Unity. Internal caching and blazing fast component access makes it second to none. Several design decisions have been made to work optimal in a garbage collected environment and to go easy on the garbage collector. Entitas comes with an optional code generator which radically reduces the amount of code you have to write and &a href=&http://link.zhihu.com/?target=https%3A//cleancoders.com/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&makes your code read like well written prose.&/a&&/blockquote&&p&以上是 Entitas 官方介绍,简单来说该框架提供了代码生成器,只需要按照它的规范实现组件和系统,便可以一键生成我们需要的属性和方法,同时为了方便我们在系统中获得感兴趣的组件,它还提供了强大的分组、匹配功能。多说无益,直接开始实战吧。&/p&&h2&2. 实战&/h2&&p&下载&a href=&http://link.zhihu.com/?target=https%3A//store.unity.com/cn& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Unity3d游戏引擎&/a&的步骤这里就省略了,我们先从 &a href=&http://link.zhihu.com/?target=https%3A//github.com/sschmid/Entitas-CSharp/releases& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Github&/a& 上下载 Entitas,笔者这里使用的是 &a href=&http://link.zhihu.com/?target=https%3A//github.com/sschmid/Entitas-CSharp/releases/tag/0.42.4& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Entitas 0.42.4&/a& 。下载好解压后,将其 CodeGenerator 和 Entitas 目录导入到一个新的 Unity 工程(这里一切从简,创建了一个空的 2D 项目),如下图所示。&/p&&p&&br&&/p&&figure&&img src=&https://pic4.zhimg.com/v2-1adef48c13b9231cfaebcaf_b.jpg& data-caption=&& data-rawwidth=&578& data-rawheight=&646& class=&origin_image zh-lightbox-thumb& width=&578& data-original=&https://pic4.zhimg.com/v2-1adef48c13b9231cfaebcaf_r.jpg&&&/figure&&p&&br&&/p&&p&接着,在工具栏找到 Tools -& Entitas -&Preference 对 Entitas 进行配置,由于这只是一个演示 ECS架构的小 Demo,就不对各种配置项进行解释了,对这些感兴趣的同学可以去官网查看文档,配置如下:&/p&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-c0af77c9ace_b.jpg& data-caption=&& data-rawwidth=&898& data-rawheight=&1194& class=&origin_image zh-lightbox-thumb& width=&898& data-original=&https://pic3.zhimg.com/v2-c0af77c9ace_r.jpg&&&/figure&&p&&br&&/p&&p&点击绿色按钮 Generate,如果没有任何报错,则配置没有问题。接下来就可以开始写代码了。&/p&&p&我们 Demo 的目标是控制一个矩形进行上下左右移动。由上文可知,我们至少需要 2 个组件:&code&PositionComponent&/code&和&code&VelocityComponent&/code&。在 Scripts/Components 目录下分别新建这两个脚本:&/p&&div class=&highlight&&&pre&&code class=&language-csharp&&&span&&/span&&span class=&c1&&// PositionComponent.cs&/span&
&span class=&k&&using&/span& &span class=&nn&&Entitas&/span&&span class=&p&&;&/span&
&span class=&k&&using&/span& &span class=&nn&&UnityEngine&/span&&span class=&p&&;&/span&
&span class=&k&&public&/span& &span class=&k&&class&/span& &span class=&nc&&PositionComponent&/span& &span class=&p&&:&/span& &span class=&n&&IComponent&/span&
&span class=&p&&{&/span&
&span class=&k&&public&/span& &span class=&n&&Vector2&/span& &span class=&n&&Value&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&c1&&// VelocityComponent.cs&/span&
&span class=&k&&using&/span& &span class=&nn&&Entitas&/span&&span class=&p&&;&/span&
&span class=&k&&using&/span& &span class=&nn&&UnityEngine&/span&&span class=&p&&;&/span&
&span class=&k&&public&/span& &span class=&k&&class&/span& &span class=&nc&&VelocityComponent&/span& &span class=&p&&:&/span& &span class=&n&&IComponent&/span& &span class=&p&&{&/span&
&span class=&k&&public&/span& &span class=&n&&Vector2&/span& &span class=&n&&Value&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&/code&&/pre&&/div&&p&由于在我们 Demo 中,玩家只能操控一个矩形,我们需要对其进行标记,告诉系统这个实体是玩家的代表,于是我们还要加上一个&code&PlayerComponent&/code&来进行标记。&/p&&div class=&highlight&&&pre&&code class=&language-csharp&&&span&&/span&&span class=&c1&&// PlayerComponent.cs&/span&
&span class=&k&&using&/span& &span class=&nn&&Entitas&/span&&span class=&p&&;&/span&
&span class=&k&&public&/span& &span class=&k&&class&/span& &span class=&nc&&PlayerComponent&/span& &span class=&p&&:&/span& &span class=&n&&IComponent&/span& &span class=&p&&{&/span& &span class=&p&&}&/span&
&/code&&/pre&&/div&&p&它不需要任何数据,仅仅用自身就可以实现标记的效果,拥有该组件的实体便是我们玩家控制的代表了。&/p&&p&实现完这 3 个组件后,我们需要利用 Entitas 框架提供的代码生成器,生成一下相应的代码,Tools -& Entitas -& Generate 或者快捷键&code&control + shift + g&/code&。&/p&&p&&br&&/p&&figure&&img src=&https://pic4.zhimg.com/v2-a959c0e7f8c1e9a39662f_b.jpg& data-caption=&& data-rawwidth=&478& data-rawheight=&166& class=&origin_image zh-lightbox-thumb& width=&478& data-original=&https://pic4.zhimg.com/v2-a959c0e7f8c1e9a39662f_r.jpg&&&/figure&&p&&br&&/p&&p&没有看到任何报错,很好我们继续。&/p&&p&接着我们要实现&code&ChangePlayerVelocitySystem&/code&,它每一帧都会运行,根据玩家是否输入&code&w&/code&、&code&a&/code&、&code&s&/code&、&code&d&/code&来改变矩形的速度。&/p&&div class=&highlight&&&pre&&code class=&language-csharp&&&span&&/span&&span class=&c1&&// ChangePlayerVelocitySystem.cs&/span&
&span class=&k&&using&/span& &span class=&nn&&Entitas&/span&&span class=&p&&;&/span&
&span class=&k&&using&/span& &span class=&nn&&UnityEngine&/span&&span class=&p&&;&/span&
&span class=&k&&public&/span& &span class=&k&&class&/span& &span class=&nc&&ChangePlayerVelocitySystem&/span& &span class=&p&&:&/span& &span class=&n&&IExecuteSystem&/span&
&span class=&p&&{&/span&
&span class=&c1&&// 每一帧都会执行&/span&
&span class=&k&&public&/span& &span class=&k&&void&/span& &span class=&nf&&Execute&/span&&span class=&p&&()&/span&
&span class=&p&&{&/span&
&span class=&c1&&// 得到拥有 Player、Position、Velocity 组件的实体集合&/span&
&span class=&kt&&var&/span& &span class=&n&&playerCollection&/span& &span class=&p&&=&/span& &span class=&n&&Contexts&/span&&span class=&p&&.&/span&&span class=&n&&sharedInstance&/span&&span class=&p&&.&/span&&span class=&n&&game&/span&&span class=&p&&.&/span&&span class=&n&&GetGroup&/span&&span class=&p&&(&/span&
&span class=&n&&GameMatcher&/span&&span class=&p&&.&/span&&span class=&n&&AllOf&/span&&span class=&p&&(&/span&
&span class=&n&&GameMatcher&/span&&span class=&p&&.&/span&&span class=&n&&Player&/span&&span class=&p&&,&/span&
&span class=&n&&GameMatcher&/span&&span class=&p&&.&/span&&span class=&n&&Position&/span&&span class=&p&&,&/span&
&span class=&n&&GameMatcher&/span&&span class=&p&&.&/span&&span class=&n&&Velocity&/span&&span class=&p&&));&/span&
&span class=&kt&&var&/span& &span class=&n&&velocity&/span& &span class=&p&&=&/span& &span class=&n&&Vector2&/span&&span class=&p&&.&/span&&span class=&n&&zero&/span&&span class=&p&&;&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&n&&Input&/span&&span class=&p&&.&/span&&span class=&n&&GetKey&/span&&span class=&p&&(&/span&&span class=&n&&KeyCode&/span&&span class=&p&&.&/span&&span class=&n&&W&/span&&span class=&p&&))&/span&
&span class=&p&&{&/span&
&span class=&n&&velocity&/span&&span class=&p&&.&/span&&span class=&n&&y&/span& &span class=&p&&+=&/span& &span class=&m&&1&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&n&&Input&/span&&span class=&p&&.&/span&&span class=&n&&GetKey&/span&&span class=&p&&(&/span&&span class=&n&&KeyCode&/span&&span class=&p&&.&/span&&span class=&n&&S&/span&&span class=&p&&))&/span&
&span class=&p&&{&/span&
&span class=&n&&velocity&/span&&span class=&p&&.&/span&&span class=&n&&y&/span& &span class=&p&&-=&/span& &span class=&m&&1&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&n&&Input&/span&&span class=&p&&.&/span&&span class=&n&&GetKey&/span&&span class=&p&&(&/span&&span class=&n&&KeyCode&/span&&span class=&p&&.&/span&&span class=&n&&A&/span&&span class=&p&&))&/span&
&span class=&p&&{&/span&
&span class=&n&&velocity&/span&&span class=&p&&.&/span&&span class=&n&&x&/span& &span class=&p&&-=&/span& &span class=&m&&1&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&n&&Input&/span&&span class=&p&&.&/span&&span class=&n&&GetKey&/span&&span class=&p&&(&/span&&span class=&n&&KeyCode&/span&&span class=&p&&.&/span&&span class=&n&&D&/span&&span class=&p&&))&/span&
&span class=&p&&{&/span&
&span class=&n&&velocity&/span&&span class=&p&&.&/span&&span class=&n&&x&/span& &span class=&p&&+=&/span& &span class=&m&&1&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&k&&foreach&/span& &span class=&p&&(&/span&&span class=&kt&&var&/span& &span class=&n&&player&/span& &span class=&k&&in&/span& &span class=&n&&playerCollection&/span&&span class=&p&&)&/span&
&span class=&p&&{&/span&
&span class=&n&&player&/span&&span class=&p&&.&/span&&span class=&n&&ReplaceVelocity&/span&&span class=&p&&(&/span&&span class=&n&&velocity&/span&&span class=&p&&);&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&/code&&/pre&&/div&&p&这里实现了&code&IExecuteSystem&/code&接口,每一帧其&code&Execute&/code&方法都会执行。&/p&&p&至此,我们每一帧都会根据用户的输入去改变矩形的速度,还需要一个&code&ChangePositionSystem&/code&,它会根据实体身上速度组件的值,去改变位置组件的值。&/p&&div class=&highlight&&&pre&&code class=&language-csharp&&&span&&/span&&span class=&c1&&// ChangePositionSystem.cs&/span&
&span class=&k&&using&/span& &span class=&nn&&System.Collections.Generic&/span&&span class=&p&&;&/span&
&span class=&k&&using&/span& &span class=&nn&&Entitas&/span&&span class=&p&&;&/span&
&span class=&k&&using&/span& &span class=&nn&&UnityEngine&/span&&span class=&p&&;&/span&
&span class=&k&&public&/span& &span class=&k&&class&/span& &span class=&nc&&ChangePositionSystem&/span& &span class=&p&&:&/span& &span class=&n&&ReactiveSystem&/span&&span class=&p&&&&/span&&span class=&n&&GameEntity&/span&&span class=&p&&&&/span&
&span class=&p&&{&/span&
&span class=&k&&public&/span& &span class=&nf&&ChangePositionSystem&/span&&span class=&p&&(&/span&&span class=&n&&Contexts&/span& &span class=&n&&contexts&/span&&span class=&p&&)&/span& &span class=&p&&:&/span& &span class=&k&&base&/span&&span class=&p&&(&/span&&span class=&n&&contexts&/span&&span class=&p&&.&/span&&span class=&n&&game&/span&&span class=&p&&)&/span&
&span class=&p&&{&/span&
&span class=&p&&}&/span&
&span class=&k&&protected&/span& &span class=&k&&override&/span& &span class=&n&&ICollector&/span&&span class=&p&&&&/span&&span class=&n&&GameEntity&/span&&span class=&p&&&&/span& &span class=&n&&GetTrigger&/span&&span class=&p&&(&/span&&span class=&n&&IContext&/span&&span class=&p&&&&/span&&span class=&n&&GameEntity&/span&&span class=&p&&&&/span& &span class=&n&&context&/span&&span class=&p&&)&/span&
&span class=&p&&{&/span&
&span class=&k&&return&/span& &span class=&n&&context&/span&&span class=&p&&.&/span&&span class=&n&&CreateCollector&/span&&span class=&p&&(&/span&&span class=&n&&GameMatcher&/span&&span class=&p&&.&/span&&span class=&n&&AllOf&/span&&span class=&p&&(&/span&&span class=&n&&GameMatcher&/span&&span class=&p&&.&/span&&span class=&n&&Position&/span&&span class=&p&&,&/span& &span class=&n&&GameMatcher&/span&&span class=&p&&.&/span&&span class=&n&&Velocity&/span&&span class=&p&&));&/span&
&span class=&p&&}&/span&
&span class=&k&&protected&/span& &span class=&k&&override&/span& &span class=&kt&&bool&/span& &span class=&nf&&Filter&/span&&span class=&p&&(&/span&&span class=&n&&GameEntity&/span& &span class=&n&&entity&/span&&span class=&p&&)&/span&
&span class=&p&&{&/span&
&span class=&k&&return&/span& &span class=&n&&entity&/span&&span class=&p&&.&/span&&span class=&n&&hasPosition&/span& &span class=&p&&&&&/span& &span class=&n&&entity&/span&&span class=&p&&.&/span&&span class=&n&&hasVelocity&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&k&&protected&/span& &span class=&k&&override&/span& &span class=&k&&void&/span& &span class=&nf&&Execute&/span&&span class=&p&&(&/span&&span class=&n&&List&/span&&span class=&p&&&&/span&&span class=&n&&GameEntity&/span&&span class=&p&&&&/span& &span class=&n&&entities&/span&&span class=&p&&)&/span&
&span class=&p&&{&/span&
&span class=&k&&foreach&/span& &span class=&p&&(&/span&&span class=&kt&&var&/span& &span class=&n&&entity&/span& &span class=&k&&in&/span& &span class=&n&&entities&/span&&span class=&p&&)&/span&
&span class=&p&&{&/span&
&span class=&kt&&var&/span& &span class=&n&&velocity&/span& &span class=&p&&=&/span& &span class=&n&&entity&/span&&span class=&p&&.&/span&&span class=&n&&velocity&/span&&span class=&p&&.&/span&&span class=&n&&Value&/span&&span class=&p&&;&/span&
&span class=&kt&&var&/span& &span class=&n&&newPosition&/span& &span class=&p&&=&/span& &span class=&n&&entity&/span&&span class=&p&&.&/span&&span class=&n&&position&/span&&span class=&p&&.&/span&&span class=&n&&Value&/span& &span class=&p&&+&/span& &span class=&n&&velocity&/span& &span class=&p&&*&/span& &span class=&n&&Time&/span&&span class=&p&&.&/span&&span class=&n&&deltaTime&/span&&span class=&p&&;&/span&
&span class=&n&&entity&/span&&span class=&p&&.&/span&&span class=&n&&ReplacePosition&/span&&span class=&p&&(&/span&&span class=&n&&newPosition&/span&&span class=&p&&);&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&/code&&/pre&&/div&&p&这里我们用到了&code&ReactiveSystem&GameEntity&&/code&基类,稍微讲解一下,它应该算是一种特殊的&code&IExecuteSystem&/code&接口实现,它也会每一帧都执行,但它会帮助我们监听我们感兴趣的组件,只有当这些组件发生变化时,它的&code&Execute&/code&方法才会被调用,&code&GetTrigger&/code&和&code&Filter&/code&两个方法相当于过滤器,具体就不细讲了,可以去官网查看一下文档。&/p&&p&由于使用了 Unity3d 游戏引擎,我们的框架需要由引擎来驱动,因此我们还要添加一个继承自&code&MonoBehaviour&/code&的&code&GameController&/code&脚本,在其中的&code&Start&/code&方法里实例化各个系统,&code&Update&/code&方法里调用&code&Excute&/code&。&/p&&div class=&highlight&&&pre&&code class=&language-csharp&&&span&&/span&&span class=&c1&&// GameController.cs&/span&
&span class=&k&&using&/span& &span class=&nn&&UnityEngine&/span&&span class=&p&&;&/span&
&span class=&k&&using&/span& &span class=&nn&&Entitas&/span&&span class=&p&&;&/span&
&span class=&k&&public&/span& &span class=&k&&class&/span& &span class=&nc&&GameController&/span& &span class=&p&&:&/span& &span class=&n&&MonoBehaviour&/span&
&span class=&p&&{&/span&
&span class=&k&&private&/span& &span class=&n&&Systems&/span& &span class=&n&&_systems&/span&&span class=&p&&;&/span&
&span class=&k&&private&/span& &span class=&k&&void&/span& &span class=&nf&&Start&/span&&span class=&p&&()&/span&
&span class=&p&&{&/span&
&span class=&n&&Contexts&/span& &span class=&n&&contexts&/span& &span class=&p&&=&/span& &span class=&n&&Contexts&/span&&span class=&p&&.&/span&&span class=&n&&sharedInstance&/span&&span class=&p&&;&/span&
&span class=&c1&&// 创建系统&/span&
&span class=&n&&_systems&/span& &span class=&p&&=&/span& &span class=&n&&CreateSystems&/span&&span class=&p&&(&/span&&span class=&n&&contexts&/span&&span class=&p&&);&/span&
&span class=&c1&&// 创建我们的玩家实体&/span&
&span class=&kt&&var&/span& &span class=&n&&player&/span& &span class=&p&&=&/span& &span class=&n&&contexts&/span&&span class=&p&&.&/span&&span class=&n&&game&/span&&span class=&p&&.&/span&&span class=&n&&CreateEntity&/span&&span class=&p&&();&/span&
&span class=&c1&&// 为其添加相应的组件&/span&
&span class=&n&&player&/span&&span class=&p&&.&/span&&span class=&n&&isPlayer&/span& &span class=&p&&=&/span& &span class=&k&&true&/span&&span class=&p&&;&/span&
&span class=&n&&player&/span&&span class=&p&&.&/span&&span class=&n&&AddPosition&/span&&span class=&p&&(&/span&&span class=&n&&Vector2&/span&&span class=&p&&.&/span&&span class=&n&&zero&/span&&span class=&p&&);&/span&
&span class=&n&&player&/span&&span class=&p&&.&/span&&span class=&n&&AddVelocity&/span&&span class=&p&&(&/span&&span class=&n&&Vector2&/span&&span class=&p&&.&/span&&span class=&n&&zero&/span&&span class=&p&&);&/span&
&span class=&c1&&// 初始化系统&/span&
&span class=&n&&_systems&/span&&span class=&p&&.&/span&&span class=&n&&Initialize&/span&&span class=&p&&();&/span&
&span class=&p&&}&/span&
&span class=&k&&private&/span& &span class=&k&&void&/span& &span class=&nf&&Update&/span&&span class=&p&&()&/span&
&span class=&p&&{&/span&
&span class=&n&&_systems&/span&&span class=&p&&.&/span&&span class=&n&&Execute&/span&&span class=&p&&();&/span&
&span class=&n&&_systems&/span&&span class=&p&&.&/span&&span class=&n&&Cleanup&/span&&span class=&p&&();&/span&
&span class=&p&&}&/span&
&span class=&k&&private&/span& &span class=&k&&void&/span& &span class=&nf&&OnDestroy&/span&&span class=&p&&()&/span&
&span class=&p&&{&/span&
&span class=&n&&_systems&/span&&span class=&p&&.&/span&&span class=&n&&TearDown&/span&&span class=&p&&();&/span&
&span class=&p&&}&/span&
&span class=&k&&private&/span& &span class=&n&&Systems&/span& &span class=&nf&&CreateSystems&/span&&span class=&p&&(&/span&&span class=&n&&Contexts&/span& &span class=&n&&contexts&/span&&span class=&p&&)&/span&
&span class=&p&&{&/span&
&span class=&c1&&// Feature 是 Entitas 框架提供的在 Editor 下进行调试的类&/span&
&span class=&k&&return&/span& &span class=&k&&new&/span& &span class=&nf&&Feature&/span&&span class=&p&&(&/span&&span class=&s&&&Game&&/span&&span class=&p&&)&/span&
&span class=&p&&.&/span&&span class=&n&&Add&/span&&span class=&p&&(&/span&&span class=&k&&new&/span& &span class=&n&&ChangePlayerVelocitySystem&/span&&span class=&p&&())&/span&
&span class=&p&&.&/span&&span class=&n&&Add&/span&&span class=&p&&(&/span&&span class=&k&&new&/span& &span class=&n&&ChangePositionSystem&/span&&span class=&p&&(&/span&&span class=&n&&contexts&/span&&span class=&p&&));&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&/code&&/pre&&/div&&p&在场景中新建一个名为“GameController”的空物体,将该脚本添加上去,运行游戏,在“Hierarchy”页签下就可以看到我们创建的系统和实体了,如下图:&/p&&figure&&img src=&https://pic4.zhimg.com/v2-53cb18bbf6cea39a2f2df_b.jpg& data-caption=&& data-rawwidth=&1588& data-rawheight=&1254& class=&origin_image zh-lightbox-thumb& width=&1588& data-original=&https://pic4.zhimg.com/v2-53cb18bbf6cea39a2f2df_r.jpg&&&/figure&&p&当我们按下&code&w&/code&、&code&a&/code&、&code&s&/code&、&code&d&/code&时,可以看到左侧 Position 下面的数值和 Velocity 下面的数值都根据我们的输入产生了对应的变化,这说明功能实现的没有问题。&/p&&p&至此,虽然还没有图形显示在场景中,但一个可操控的 Demo 已经完成了。&/p&&p&为了节省篇幅,&code&SpriteComponent&/code&(精灵组件)和&code&RenderSystem&/code&(渲染系统),这里就不再展示了,完整项目可以在我的 &a href=&http://link.zhihu.com/?target=https%3A//github.com/yangruihan/ECSDemo& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Github&/a& 里查看。&/p&&h2&&b&0x04 后记&/b&&/h2&&p&到此,整篇文章也进入了尾声,不知读者是否对 ECS 架构有了自己的理解,其实笔者也是最近这段时间才开始使用该架构编写一些小项目,还未在商业项目中使用过,因此有些地方的理解可能存在一定的偏差,欢迎大家讨论与指正,感谢大家的阅读。&/p&&h2&&b&参考&/b&&/h2&&ul&&li&&a href=&http://link.zhihu.com/?target=http%3A//gad.qq.com/article/detail/28682& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&《守望先锋》架构设计与网络同步 -- GDC2017 精品分享实录&/a&(文章)&/li&&li&&a href=&http://link.zhihu.com/?target=http%3A//gad.qq.com/article/detail/29595& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&《守望先锋》回放技术-阵亡镜头、全场最佳和亮眼表现&/a&(文章)&/li&&li&&a href=&http://link.zhihu.com/?target=https%3A//blog.codingnow.com/2017/06/overwatch_ecs.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&浅谈《守望先锋》中的 ECS 构架&/a&(文章)&/li&&li&&a href=&http://link.zhihu.com/?target=https%3A//www.youtube.com/watch%3Fv%3D1wvMXur19M4& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Entity system architecture with Unity&/a&(视频)&/li&&li&&a href=&http://link.zhihu.com/?target=https%3A//www.youtube.com/watch%3Fv%3DlNTaC-JWmdI& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&ECS architecture with Unity by example&/a&(视频)&/li&&/ul&
游戏开发中的ECS 架构概述作者:C.y.Github:0x00 何为ECS架构ECS,即 Entity-Component-System(实体-组件-系统) 的缩写,其模式遵循原则,游戏内的每一个基本单元都是一个实体,每个实体又由一个或多个组件构成,每个组件…
&p&先说现象,的确,我们在平台上也经常会碰到所谓被「技术瓶颈」困扰的程序员。&/p&&p&通常这样的&b&瓶颈症候群&/b&表现除了如题主所说的觉得没有进步了之外,还有如下表现:失去了主动学习的热情,不再刻苦专研技术,长时间消息闭塞,对新技术、新领域不了解。&/p&&p&这些现状听上去真的让人「十分焦虑」。&/p&&p&那么问题来了,产生技术瓶颈背后的原因有哪些?&br&如果真的存在,应该用什么样的方法来克服?&/p&&p&这个回答分为&b&两个部分&/b&:&/p&&ol&&li&技术瓶颈产生的原因&/li&&li&如何克服这些技术瓶颈(想直接看方法论的知友可以从这个部分开始)&/li&&/ol&&hr&&h2&产生技术瓶颈的原因&/h2&&ol&&li&&b&无危机意识、无上升意识&/b&&br&很多程序员在经历最开始第一年的「钻研与学习」之路后,当技能逐渐熟练,解决工作内容显得得心应手时,他们会失去好奇心,失去压迫感,从而满足现状;放低自身要求,认为编程技术在满足开发软件需求情况下,编出来就行,如果要达到更苛刻标准,纯看上司要求,或自身兴趣,无奈他们已然没了兴趣。&br&&br&&/li&&li&&b&加班过多挤压自己对问题的深入思考时间&/b&&br&「上班已经够辛苦了,为什么下班还要折磨我?」可能是每个被加班、工作时间要求996、周末轮班工作等制度折磨的程序员的 OS 。许多程序员过度被工作消耗,甚至会出现工作稍显应付的情况,就更不要说回到家继续思考、继续精进了。&br&&br&但在其实这里更需要警惕,当自身成长速度完全取决于其工作内容的强度和难度,工龄久了,工作只有加班强度,没有技术难度,成长便会停滞,迎来真正的技术瓶颈。&br&&br&&/li&&li&&b&无法集中精力专注于编程&/b&&br&公司由于加速扩张形成的资源内耗,和老板的想法不一致,和其他诸如设计、产品等岗位的沟通占据一定精力,这些是初入技术管理或者稍微资深一点的程序员会出现的工作压力。当你开始积累类似的负能量,久而久之,恶性循环之下,就会出现分身乏力的挫败感,最后导致无论是主动学习还是钻研技术上,都失去热情。&br&但是,其实不需要沟通的技术人员根本不存在,合理利用精力用于沟通,是用技术解决问题的快捷方式之一。&/li&&/ol&&hr&&h2&如何克服技术瓶颈?&/h2&&p&扔掉借口从改变环境做起,跳槽 or 转岗?无论怎么选,都是逼迫自己改变的开始,陷在悖论中倒不如去打破僵局,打破的方法,我们从以下两点来深究。&/p&&ul&&li&&b&1. 熟练工?加班多?是你太舒适了&/b&&/li&&/ul&&p&我们近期重点跟进了一名架构师候选人,他 6 年工作经验、跳槽前年薪 64 万、持 15 万股票,纵观他职业发展路径,除去第一家公司,后三家公司皆为大厂,他在 3 年工作经验时,未遇见所谓的技术瓶颈。&/p&&p&首先,来看该候选人在 3 年经验的工作内容:&/p&&blockquote&1)承担工作为数据团队前端开发(各种 js 编写,熟悉 jquery,extjs 等常用框架及原生 js)&br&2)报表工具制作(主要适用技术是 extjs / finereport / jfreechart)&br&3)日常分析任务(mapreduce / hive)&br&4)调度系统的维护和某项目开发(前端+后端 jsp+struts2+hbase+redis+mysql+hadoop)&br&5)分析团队的定时任务的管理&/blockquote&&p&对 3 年工作经验的程序员来说,以上工作并不轻松。他在接受 100offer 采访时表明,他会先注重个人的输入,每日阅读两小时技术书籍,每周都研究源码,之后,他更看重他的有效工作,即具有创造性的输出,重复性代码是不会带来实际性成长。&/p&&p&在他发现开始做大量重复性代码、无法通过工作内容上升技术时,他选择了跳槽。&/p&&p&跳槽后,他在中间件团队工作,中间件是独立系统软件,分布式应用软件能借助该软件在不同技术间共享资源,他认为那是他「创造性输出」的最好时机,他负责了基础组件开发,主要是可靠消息系统 qmq 和异步 redis 客户端,参与研发任务调度系统,做了类鹰眼的 trace 系统、dubbo 服务化工程、监控系统等。&/p&&p&通过他的案例,能够察觉:实践始终是源于理论又高于理论的,不难发现,所谓「熟练工」、「加班多」仅是个人借口,要做的,是远离舒适区,逼迫自己成长。&/p&&p&首先,请发挥主观能动性,做出改变。我们给出以下&b&&i&两点建议&/i&&/b&——&/p&&p&1)多次&b&检阅基础知识,将有效技能掌握牢固,把各类基础知识串联成完整体系&/b&。技术不可满足现状,懂得把编程技术从功能实现转向软件构架、参数化设计等高阶方面,在共享

我要回帖

更多关于 打开exe提示停止工作 的文章

 

随机推荐