惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

G
GRAHAM CLULEY
V
V2EX
WordPress大学
WordPress大学
博客园 - Franky
Last Week in AI
Last Week in AI
博客园 - 司徒正美
有赞技术团队
有赞技术团队
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 【当耐特】
V
Visual Studio Blog
C
CERT Recently Published Vulnerability Notes
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Jina AI
Jina AI
Attack and Defense Labs
Attack and Defense Labs
腾讯CDC
The Hacker News
The Hacker News
Hugging Face - Blog
Hugging Face - Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
J
Java Code Geeks
人人都是产品经理
人人都是产品经理
阮一峰的网络日志
阮一峰的网络日志
T
Tailwind CSS Blog
S
SegmentFault 最新的问题
大猫的无限游戏
大猫的无限游戏
小众软件
小众软件
A
Arctic Wolf
量子位
博客园 - 聂微东
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
N
News and Events Feed by Topic
雷峰网
雷峰网
博客园_首页
Google Online Security Blog
Google Online Security Blog
Spread Privacy
Spread Privacy
罗磊的独立博客
H
Hacker News: Front Page
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
月光博客
月光博客
TaoSecurity Blog
TaoSecurity Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
博客园 - 三生石上(FineUI控件)
宝玉的分享
宝玉的分享
IT之家
IT之家
The Cloudflare Blog
爱范儿
爱范儿
博客园 - 叶小钗
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Apple Machine Learning Research
Apple Machine Learning Research
酷 壳 – CoolShell
酷 壳 – CoolShell

机核

游戏性能旗舰最强之选,一加 Ace 6 至尊版国补到手价2999元起 6元钱自己更换电动车刹车线 《生化危机9:安魂曲》编剧Haris Orkin专访 摸金游戏?音乐游戏!暗区新赛季这把能弹的琴有何来历? 好评国产武侠SRPG《息风谷战略》免费DLC现已推出 | 机核 GCORES 碎片 《生化危机:安魂曲》将于5月实装首个免费更新内容 | 机核 GCORES 新锐东方游戏,谱写世界新章! 沉浸式恋爱视觉小说游戏《心象演算》免费试玩版现已正式上线 | 机核 GCORES 互动影游《代号三国:龙起》上线!穿越三国与曹操并肩、与佳人同行、与权谋博弈! 《老头收集梦想生活》,游戏酒桌会6,录音笔VOL.689 | 机核 GCORES 破界·共生——《白日梦:无限世界》五大核心游戏特点解析 价格已到史低,锐龙5 9600X/锐龙7 9700X正适合抄底 时间循环之旅即刻启程!《归环》一周目测试今日开启 热门在线韩游变魂游,洛奇衍生作能否打破“花瓶”魔咒? LG UltraGear evo 全新高端显示器系列:当“5K”遇见“AI”,不止强大,更懂热爱 反套路三国互动影游《代号三国:龙起》今日上线! 愿望单登记人数突破10万!备受瞩目的“女儿养成游戏” 《梦幻魔法公主》今日于Steam平台上线!限时八折优惠中 《黑神话:悟空》全球音乐会2026巡演将于4月29日12时开票 | 机核 GCORES “Snowguelike”生存肉鸽挖矿新作《蛙穿雪境》公布发售日期,5月7日正式上线 | 机核 GCORES 重塑移动办公、AI创作新境!全新华硕灵耀Air系列、ProArt 骁龙版震撼首发,创芯未来 均分88:《Saros》媒体评分汇总 | 机核 GCORES 上海烛龙公布合作遗迹探险游戏《吉时已到》首支预告片 | 机核 GCORES 首个独立游戏《萝薇日记》已上线Steam! 烛龙新IP《吉时已到》首曝,打造国内首款中式合作遗迹探险游戏 喜加一:《暗黑破坏神Ⅳ》国服现已开启限时免费领取本体活动 | 机核 GCORES 新版《生化危机》电影定于9月18日上映,官方网站现已上线 | 机核 GCORES 《冲就完事模拟器2》“星球大战”联动DLC正式宣布 | 机核 GCORES SteamController将于5月4日发售,售价99美元 | 机核 GCORES 事已至此,内存这么用也算省钱了,“2+1”非对称双通道应用实测 505游戏母公司现已收购《明末:渊虚之羽》IP | 机核 GCORES 基石 手动杂谈12|格斗游戏也能讲好故事 | 机核 GCORES I Love You Mr Snowball 我的向日葵小姐 会比GTA6先发售吗?最硬核的生存游戏《DAYZ》要推新DLC了 周记02:在2026遇到新怪谈 什么硬件,能让游戏Loading界面快速消失? | 机核 GCORES GadioSpec《百年风云世界杯》免费试听集 | 机核 GCORES 百年风云世界杯Vol.1丨足球崛起 | 机核 GCORES 100年前,一群人提前替我们经历了AI恐惧 | 机核 GCORES 《呼啸山庄》2026 ——一辆当代艺术的大卡车冲撞了我的大脑 手游《天穗之咲稻姬:日之香巡灵传》宣布将于7月27日停服 | 机核 GCORES 集结梦之队,征战世界杯,《最佳球会ONLINE》上线Steam 山水绝景随心拼 休闲建造游戏《千里山河录》Steam商店页公开 巫师帽、法袍、魔杖,为什么它们是影视、游戏里的法师必备三件套? 《无鞘信使》-第一章 复古风自动战斗肉鸽《终结之终结》Steam商店页面现已上线 电脑里有一款不破不立的MMO,录音笔VOL.688 | 机核 GCORES 《生化危机》30周年纪念周边发售,这次是真的“保护伞” 可靠耐用+AI全能,惠普战66 2025锐龙版深度体验 《时之书:无尽终章》关卡“大航海时代”全球首次公开 经典名作《乌龙派出所》改编经营模拟游戏《乌龙派出所~阿两的商店街物语~》正式宣布支持简体中文 明日开冲,解锁反套路三国互动影游《代号三国:龙起》即将上线 独立游戏《这是我的宝藏!》已发售~ 降低难度不是唯一解,无压力死亡也是好体验 Netflix官宣新片《普通人》:讲述韩国现代史上的权力风暴 《生化危机:安魂曲》全球销量现已突破700万份 《绝地鸭卫》PC版5月15日正式发售 亡妻回忆录?女性向情感叙事游戏《S-mail》现已正式发售 全新酷黑风格,酷睿Ultra 200S PLUS的高性价比搭档!七彩虹BATTLE-AX B860M-PLUS S WIFI7 V20 超级黑刃主板测评 胖狗 索尼发布了港台地区PS5产品价格调整公告,将于5月1日起实施 二次元怪猎+性感美女!《碧蓝幻想:无尽黄昏》开启Beta公测 这款怪谈类型中式恐怖游戏居然更新了?! 《百日战纪 -最终防卫学园-》改编漫画将于今年冬季开启连载 《如被附身,请致电我们》:匈牙利黑色幽默恐怖小说 《竹屿山房杂部卷五》(译文) 大树 超越引擎 摄影分享丨四月 碎片杂记vol.72 当老式FPS与老式动画技术碰撞出新时代的火花—《神探杰克鼠》 想做独游,如何避免首个项目就褒姒? 在线多人动作游戏《OCTOPinbs》将于5月12日上线Steam! 《酒鬼女神的酒诡》确定将于2026年登陆Steam 《CRYMELIGHT》将于11月5日(周四)正式发售!4月25日开始预购! 钢铁国度MKI部落Evolution,蛮兵部分 【钢铁国度】部落-Primal MK I,蛮兵部分 这是一个高中生用ai跑出来的作品,我自称他为物理神话 钢铁国度MKI部落Metamorphosis,蛮兵部分上 钢铁国度MKI部落Metamorphosis,蛮兵部分下 INDIE Live Expo于4月25日举办:首发9款新作,超200款独立游戏亮相 暗黑卡牌策略新作《魔忌:穷鼠啮狸》发布全新中文试玩版和发售预告片,4月30日正式上线在即 战锤40K长篇小说:变节者・苦难主宰(三)(全书完) 战锤40K长篇小说:变节者・苦难主宰(二) 战锤40K长篇小说:变节者・苦难主宰(一) 英语语言学习丨短语专题1:短语的特点 唯一的EVE战争 【少前同人】【M200】战术人形会梦见音乐会吗 【昏迷3】即将发售,前作主角悉数到场!“恶灵”宋老师化身可操控角色 业内人士:游戏公司“十有八九”使用生成式AI,包括卡普空 欢庆一周年:《光与影:33号远征队》全新纪念艺术图、超值折扣与免费更新同步上线 才刚刚开始呢 【抽奖】《星际卡车司机》推出免费大型更新,四折平史低折扣进行中 四人合作FPS游戏《佣兵猎手》抢先体验重大更新 1 现已上线 Raw Fury新作《深馅地牢 Deep Dish Dungeon》将于今秋加入 XGP 塔防幸存者游戏《魔怪来袭》推出首个 DLC 《饿狼传说:群狼之城》1周年纪念!新DLC“沃尔夫冈·克劳萨”今日参战 猫狗相伴 欢乐闯关 双人合作平台跳跃游戏《猫狗同行》上线Steam商店页 《同行:月球逃脱》(Together: Moon Escape)上线将于明日上线Steam
GDC 粗读丨看看《心灵杀手2》中的面向数据编程——ECS
Hakumen · 2025-01-10 · via 机核

前言

比起SIGGRAPH来说,GDC Vault里虽然也有大量游戏开发相关的知识分享,但由于主要是视频为主,因此能被我拿来作为二手知识粗读一遍的文稿类内容相对没那么多;另外,GDC提供的PPT原稿里面是不附带解说稿的,所以其实详细程度是不如看原视频的。在这之中,偶尔还是能翻出一些详略合适的内容(比如之前也读过的《HiFi-Rush》和《赛博朋克2077》)。

ECS是Entity Component System的缩写,虽然从名称看不出其对于内存连续性并行执行的意义,但它已经是行业公认的代表面向数据编程的设计模式框架。文末会附一篇Games104介绍ECS部分的链接。

本人虽然没有实际参与过ECS模式的内容开发,只是粗略体验过Unity(DOTS)和Unreal(Mass)的示例,但这次难得看到一篇ECS系统在3A游戏中实际应用,出于个人好奇还是带大家一起读一下。

这篇粗读以翻译原文稿的PPT页内容为主, 打星号的部分则是我个人的补充说明。

1 系统框架概述

NorthLight是一个聚焦的、艺术家导向的游戏引擎和工具套件——由Remedy Entertaiment开发,赋权给我们现在和未来开发的游戏。

在创造工业化导向的游戏视觉方面不断进行技术演进:

  • 《量子破碎》中顶尖的面部动画

  • 《控制》中(Remedy产品)首次使用的硬件光线追踪

对于《心灵杀手2》,NorthLight有着多项提升:

  • GPU驱动的管线

  • 基于SDF的风系统

  • 植被控制

  • 更多可以参见remedy官方提供的链接

  • 在2021年,新的ECS(Entity Component System)物体模组在NL中被启用了。

  • 它替代了之前使用的重度面向对象(OOP)实体组件框架,通过预定义的函数和事件图来连接不同的实体之上的组件。

  • ECS是一个软件设计方案,它通过分离数据和行为来改进代码的重用度。其中数据被以一个缓存友好的方式存储,以提升性能。

  • 一个缓存友好的数据分布,和NL ECS的易于并行化都能提升性能。

  • 更重要的是,它能使游戏玩法的程序员更易于理解游戏逻辑的执行流程。

NL引擎的ECS有如下特点:

  • 它有实体(entities)概念,它们是有唯一性的标识符。

  • 组件(components)概念,是纯数据类型(的结构),不执行行为。

  • 组件可以被动态增加或移除。

  • 它有系统(system)概念,是由包含特定组件的实体匹配而成的函数功能。

  • 系统访问数据的读写操作定义可以在编译时就进行验证,而这是一个强项。

*之所以可以在编译时验证是一定程度放弃了“动态类型”的,后面看例子就能看出。

  • 组件是纯数据结构,用来表达一个状态。

  • 它们不应包含任何行为,而只有状态数据。

  • 如果你需要提供一个公用接口以处理组件数据(以某种方式),可以采用一个自由函数传入这个组件(作为参数)的方式,而不是作为组件的函数方法(method)。

*PPT页中可以看到血量计算函数的具体写法。

  • 环境保存游戏中能被全局访问的数据。

  • 它们直接存在于内存中,而不与任何实体关联。

  • 任何环境类型只以单例的形式存在于游戏中。

*PPT页中可以看到以游戏光标为例的一套写法,包含基本结构、更新位置、绘制。

  • 实体是一个概念上的物体,由被称为组件的数据结构组成——每个组件代表了该物体的一类特定功能。

  • 一个实体由其关联的组件集合来定义。对于实体来说并不存在具体的“物体”概念。

  • 一个实体能被一个32位的整型数标识(相当于ID)。

  • 代码中仍有能表达单一或多个实体,并访问其组件的方式。

  • 访问定义是一个模板化的数据结构,它允许定义一次数据访问(的内容)。

  • 它是用于使ECS系统理解你的依赖项的。

*可以看到PPT页中的类似面向过程的语法,以及一些基础的模板样式。

定义链通常以一个特定的访问范围定义作为结尾(如果需要的话),以指明从一个实体或一个集合中读取数据。

*PPT页中的Group和Query都是对应集合类型。

  • 一个ECS中的系统是一个自由函数,它能接收一些输入、进行处理并产生一些输出给组件。

  • 系统也能添加或移除组件。

  • 系统使用访问环境作为参数。

*PPT页中引用了两个实体:可受伤角色实体、伤害来源实体。而系统函数主要内容是基于一组伤害来源(查询)进行定时伤害结算。

为使一个系统生效,我们需要将其注册到游戏循环中。

我们可以将其注册到不同的游戏循环阶段中——对应系统组的概念:

  • 可变更新

  • 固定更新

  • 固定更新前的可变更新

当注册系统时,添加依赖项来影响系统的执行顺序是可行的。如果没有指定顺序,则系统会按访问需求的顺序执行。

*这里update模块的细节作者没有给出。

*由于游戏中所有类型的执行逻辑都要放在各种系统函数中集中执行,可想而知这套框架不适合处理逻辑过于复杂并且耦合较重的游戏逻辑。

2 案例解析——THE CASE BOARD

  • (女主角)Saga搜集证据的串联图板。

  • 她能通过放置线索,并将其与游戏中获得的其它信息组合来推进调查进度。

  • 它主要的功能是帮助玩家梳理故事线,并更加投入其中。

  • 某些游戏中的事件只能被案件板中线索的组合来触发。

玩家在游戏中能搜集不同类型的线索(通过交互、拾取、调查实景模型,以及脚本事件)。

  • 玩家通过拖动操作来将线索放置在板上,并与其它线索组合。

  • 部分线索会依赖案件板自身的事件触发来被放置或解锁。

游戏中会有多项进行中的调查,玩家可以在它们之间切换。

案件信息的布局是通过一个编辑工具定义的——它是由Remedy的主UI/UX设计师Riho Kroll开发的。它能允许叙事设计师以所见即所得的方式编辑案件。(*What you see is what you get)

案件布局数据会被导出成一个配置文件(lua格式),并用于游戏中。

  • 代码以一组模块作为组织结构。

  • 模块至少由一个头文件和一个.cpp文件。(*C++语言)

  • 每个模块有一个或多个系统。

  • 对于案件板的模块,其中有一组模块,各自以应对特定的功能特性。

  • 也有一组与其它游玩系统共享的模块。

*简单看看案件板模块,其中有例如:案件板模块、手模块、案件绘制模块、案件道具生成等。而共享模块有:游戏光标模块、摄像机追拍模块、动作模块等。

  • 板上的每个案件是一颗线索条目的“树”。

  • 线索条目是玩家在案件板上操作的主要物体。

  • 当一个线索条目执行了某些动作后(例如:放下、解锁、组合),一个或更多的规则可能被触发。

  • 每个规则可能调用一些其他的动作(放置条目、解锁至手上、移除条目等),以应对特定条件被满足的场合(某些道具被放置、解锁等)。

  • 线索条目可以通过以下方式被放置到板上:被玩家从“手”上放下;通过触发规则;显式通过脚本调用。

线索条目可能有如下类型:

  • 案件——一个调查文件夹条目。是所有条目的父节点,被自动放置。

  • 照片——开启一个新调查分支。通过手部操作放置。

  • 线索——拍立得照片、引用、手稿页。由玩家在游戏过程中收集,通过手来放置。当与问题成功组合后能被放置在板上。

  • 推理——当所有线索被与问题组合后,会被自动放置在问题下方。

我们将所有案件(名称、条目集合)、条目描述、状态(放置、解锁、挂载父节点)存储在一个环境中。

从以下角度来看这(种设计)很有用:

  • 很便于从配置文件中加载数据。

  • 这是一个同步点。当我们想修改当前案件板的逻辑状态时,特别是从脚本调用时,我们都需要通过案件板环境。

  • 非常便于加载案件板的状态。

这种方案中,为一个线索条目执行任何动作会如下实现(图中)。

这是一个自由C++函数,传入itemId和一个案件板环境的可变的引用作为参数。

在这个函数中我们将执行如下步骤:

  • 找到环境中某条目的一个可变指针

  • 修改(需要的)状态。

  • 执行动作特有的逻辑。

  • 处理动作特有的规则。

*引用reference和指针pointer是一组C++概念。

这一模块与“真实世界”条目实体一起生效,主要负责:

  • 更新条目状态。

  • 更新板上的条目的空间变换。

逻辑被拆分成不同的系统。这是非常必要的,因为计算和应用最终的空间变换不如它看上去那么容易。

这也使我们能:

  • 避免锁定非必须的数据,以至于阻碍其它游戏系统的执行(例如空间变换)。

  • 在可行时并行执行系统。

  • 确保特定的逻辑应用到所有需要的实体上——在执行下一步骤前。

  • 在(开发中)的很长时间里,线索条目是能通过光标在板上随意放置的。

  • 当移动一个条目时,所有子条目需要保持其基于父条目的偏移值(一起移动)。

  • 条目可以叠放并堆叠起来。

  • 并且,它们的位置不能超过板的边界。

整套位置机制被拆分为多个系统,逐个执行:

  1. 更新状态和偏移值,尤其是通过案件板环境设置的“真实世界”实体。

  2. 设置条目的XY位置和边界——基于偏移值和案件板边界。

  3. 检验条目的叠放,以确认其上下关系:基于层级、条目类型、条目索引、(是否)最后被操作等。

  4. 基于叠放信息对深度排序,以计算相关的Z值。

  5. 设置条目的最终空间变换值(或直接通过动画的方式)。

*系统执行顺序是通过excuteAfter语法来确保的。

  • 我们定义了一个组件结构以存储所有的itemId和状态。

  • 我们通过环境中存储的条目状态来比较组件的状态,在必要时对组件做修改。

  • 关键的访问是对于条目的实体的,因此系统可以潜在的在一个实体层级上并行执行:对于每个实体,一个系统在其所述的线程中执行。

*案件板item的具体数据结构及状态函数。

  • 在更新了条目状态,并读取它的偏移值数据后,我们需要更新它(和板位置相关)的XY位置和边界——把板的限制列入考虑。

  • 为存储这些值,我们特定了一个新的组件用于条目的XY边界。(*提到的ItemBoundaries组件)

  • 这一系统将从条目组件中读取条目的状态,或许网格组件的外延值,并写入ItemBoundaries组件。

*边界处理——基于三个二维向量,中心、最小值、最大值。

  • 在我们更新了条目的中心和边界后,我们可以检测叠放在一起的条目。

  • 这(计算的信息)被用于后续更新条目的深度。

  • 系统的关键访问是(特定的叠放物)实体,但我们也需要分别查询所有其它条目。(*这句的意思可以参照后面的函数体)

  • 如果我们想保持一个实体层级的并行执行,我们需要确保在一次查询访问时不读写同一实体。(*否则就要改串行或者考虑加锁了)

  • 然而,将叠放结果写入一个单独(分开)的组件中也是必要的。

*前面提到的特定单个实体是OverlappedItemsEntity类型的实体,后续需要写入叠放计算结果;查询的是通过ItemBoundariesQuery以访问其它Item实体,并通过itemsHaveOverlap和isItemBelow函数来确定上下层级;计算的结果写入itemsBelow容器中。

  • 在得到所有条目的叠放信息后,我们可以对Z坐标进行排序。

  • 为实现这一点,我们创造了“层”的概念——基于某一条目其下条目的数量。

  • 为创造这些“层”,我们需要读写所有条目数据以处理全部依赖关系。(*读写的是不同的组件类型)

*这里的hasDependencies主要是上下层的依赖关系,简单来看就是通过对overlappdItems.itemBelow的整理和查询进行itemDepth的计算,并最终反应到Z值(层厚度)上。

  • 最终,在我们计算完XY和Z值后,我们为条目设置实际的空间变换。

  • 将这一逻辑放在一个独立的系统中,使我们能仅在实际需要时“锁定”变化组件,而不会阻止其它系统在一帧中的早些阶段来与其交互。

*分别计算了和板之间相对的变换boardRelativeTransform,以及世界坐标系变换worldTransform——最终实际生效的是世界坐标系变换。可以看到这里有一个动画的分支,后面会提到。

  • 实体的动画(弹簧运动)是被一个不同的(可以用于其它游玩特性的)系统来处理的。

  • 为一个条目增加动画,只用为其增加一个运动组件。

  • 当动画结束时,我们移除这一组件。

  • 我们使用一个特定的辅助物体——指令缓冲来注册这些组件的布局,并在每一帧的最后被flush。

*flush是程序开发上从缓冲区把数据汇入数据流(或进行清理)的一个概念。这个词直译的意思是“冲洗”,但这个场合没有合适的翻译;而且这部分细节后面的代码示例并没有涉及。

*这里的动画只展示了一个比较简单的基于deltaTime的程序动画示例,能实现类弹簧或摆荡的效果。具体的逻辑就是在达到目标变换值前一直tick动画系统。

3 脚本调用

*引入脚本语言的意义有很多,最容易理解的就有比如:更易于编写、不用等待编译等。这里不展开了。

  • 某些案件板功能需要开放给设计师,在脚本系统中使用。

  • 我们使用Lua作为脚本语言。

  • 我们并不在Lua端反射数据。设计师不需要考虑例如组件、访问定义等这类概念。作为替代,他们操作函数,传入实体ID作为参数。

  • 我们提供了两种从Lua端进行交互的方式:C++的Lua绑定;Lua事件。

  • 我们的Lua脚本执行于一个单线程序列。当它们被执行时,所有组件的状态都是同步过的,并且也没有其它系统在执行。这样,设计师们有不用考虑多线程相关的问题了。

Lua绑定是被组织成Lua模块的C++函数,能允许lua脚本调用C++代码。

每个Lua绑定由三部分组成:

  1. 一个绑定函数——在C++和Lua虚拟机之间传输数据,并校验输入的参数的有效性。

  2. 文档注释——用于生成VS Code中汇集式的函数说明。

  3. 类型定义——被Lua的类型校验器用于检测脚本错误。类型定义信息是基于文档注释自动生成的。

一个绑定函数的主要结构(步骤)是:

  • 从Lua参数堆栈获取参数。

  • 检验参数有效性,对于无效的类型(例如函数希望输入一个string,但传入了number)或值(例如超出范围的值),在必要时进行报错。

  • 调用C++函数或类方法以执行实际的逻辑。

  • 将返回值和返回值的数量推入Lua堆栈。

*Lua这一侧是调用示例。实际的绑定函数内容在右侧C++部分。

*以第一个函数为例,第一行注释描述了输入和返回的类型,各自就对应了checkString和pushBool调用步骤。

  • Lua事件是C++向Lua脚本通信的方式。

  • 我们使用环境(*这里还是ECS概念)LuaEvents来收集一帧中的事件。

  • 收集的事件会在下一帧开始被派遣调度。

  • 每个发送了Lua事件的系统都需要是单线程的,因为需要对LuaEvents环境进行数据写入。

*lua侧在初始化时注册了一个回调函数,而C++侧通过broadcast进行事件广播。

  • 通过ECS框架,gameplay程序员的思维模式被改变了。与处理对象不同,这个框架里我们和数据打交道。

  • 总的来说程序执行看起来很像和数据库交互,因为我们(更关注于)查询和修改数据。

  • 动态增加和移除组件的能力使我们能在运行时轻松地为不同实体开关系统。

  • 系统注册允许我们显式的指定访问同一份数据的不同系统的执行顺序。

  • 为获得更好的性能,更佳的方式就是把数据拆分成不同的组件,而不是放在一起。

  • 我们可以构造一个便利和坚固(robust,直接翻成“鲁棒”也行)脚本交互系统,它不需要设计师关心数据的分布(结构)及并行化逻辑。

结语

以我个人的角度来看,Remedy在开发这个游戏使使用ECS的必要性或许没有那么大。虽然ECS没有太多程序上的弊端,但确实在开发过程中写代码构建复杂世界时不太利于大规模并行开发;总的来说这个游戏可“游玩”的内容确实有限,除了“走路模拟”“情景解密”之外的内容不算多,这么看使用ECS是利大于弊的。

从理念角度来看,ECS更适合数据类型相对有限,但实体数量级相对会比较高的游戏。例如大量单位的即时战略游戏,或是有着大量简单行为单位的割草游戏等。我能想到的非常适合使用ECS的一个类型就是“幸存者like”游戏;而我也确实觉得几乎不可能用ECS来开发一个开放世界游戏。

另外,ECS的介绍资料其实很多,除了我提供的一些链接外有兴趣可以自行搜索。

最后是资料链接: