云风的 BLOG

思绪来得快去得也快,偶尔会在这里停留

Latest articles

为 skynet 增加并行多请求的功能

skynet 在设计时,就拒绝使用 callback 的形式来实现请求回应模式。我认为,callback 会导致业务中回应的流程和请求的流程割裂到两个执行序上,这不利于实现复杂的业务逻辑。尤其是对异常的支持不好。 所以,在 skynet 中发起请求时,当前执行序是阻塞的,一直等到远端回应,再继续在同一个执行序上延续。 如果依次发起请求,会有不该有的高延迟。因为在同一个执行序上,你必须等待前一个请求回应后,才可以提起下一个请求。而原本这个过程完全可以同时进行。 但是,如果我们想同时发起多个不相关的请求就会比较麻烦。为每个请求安排一个执行序的话,最后汇总所有请求回到一个执行序上又是一个问题。目前,只能用 fork/wait/wakeup 去实现,非常繁琐。 这类需求一直都存在。我一直想找到一个合适的方法来实现这样一类功能:同时对外发起...

银河竞逐的设计

银河竞逐 RFTG 是我最喜欢的桌游之一。我认为直到今天,它仍旧是最棒的引擎建造类卡牌游戏。最近,我看了银河竞逐的作者 Tom Lehmann 在 GDC2018 上的演讲 非常有收获,所以写这篇 Blog 分享一下。 策略竞争类的游戏一定要设计多种结束条件。RFTG 的基础版设计了建造出 12+ 张卡结束和分完 12n 个 VP 结束。基础策略就可区分为快速打出一堆小分卡,还是构造一个 VP 引擎。我最近玩得比较多的五扩(Xeno Invasion)还增加了击败(或被击溃)Xeno 结束。 这样可以使得创造出 strategic tension 。 Tom 谈了一个想法: 在炉石传说中,一般的胜利条件就是把对手的 HP 减到零。或许可以加一个胜利条件,在攻击对手的同时还可以去盖塔,当塔盖到...

Evidence-based software engineering

《The New C Standard》 是我很喜欢的一本书。因为这本书,我有幸结识了作者 Derek M Jones 。 在 2018 年的时候,他就写 email 给我介绍了他正在写的一本关于软件工程的书。 这是一本非常特别的书。里面有大量的、从公开渠道获得的关于软件工程方面的数据。作者对这些数据做了统计和分析。我之前从未看过如此全篇基于数据去讨论软件工程领域问题的著作(通常在社会学领域更多一些)。 数据摆在那里,或许不同的人,不同的方法会得到不同的解读。这本书不在于给出结论,而是展示了分析过程。让你来从中发现数据透露出的信息。 当时我就很喜欢这本书,陆陆续续读了一些。 最近,这本书《Evidence-based software engineering ——...

裁剪和空间管理

今天想谈谈游戏引擎中 Culling 模块。 当场景中的可渲染对象很多,而当前会被渲染的对象相较甚少的时候,我们通常会启用一个 culling 的过程。Culling 会想办法剔除一些当前不必渲染的对象,避免这些对象提交到 GPU ,让 GPU 承担剔除的过程。这样可以减少 CPU 到 GPU 的带宽。 最基本的 Culling 是用相机的视锥体和对象做一个相交测试,如果对象和视锥体不相交,则可判定它不必渲染;复杂的 Culling 还包括遮挡测试,如果一个对象完全被墙体挡住,那么也不必渲染。这篇只谈前者。 很容易得知,Culling 算法的复杂度上限为 O(n) 。即,我们把场景中的每个对象逐一和视锥体做一次相交判断即可。这里的 n 为场景中元素的个数。 当 n 特别大的时候,通过巧妙地设计数据结构,我们则有可能把复杂度降低。但如何做到呢?...

动态字模的管理

在上一篇 blog 中,我谈到了 UI 模块。而 UI 模块中绕不开的一个问题就是怎么实现文字渲染。 和西方文字不同,汉字的数量多达数万。想把所有文字的字模一次性烘培到贴图上未尝不可,但略显浪费。如果游戏只是用有限几种字体倒也不失一种简单明了的方法。但如果使用字体丰富,而多数字体只使用几个汉字,那么就不太妥当了。 我在设计 ejoy2d 的时候实现过一版动态字模的管理。但我觉得略显简陋。最近重新做了一版。 首先,我决定使用 SDF 来渲染字体,所以不必在贴图中管理不同大小的字模了。其次,我觉得汉字的宽度其实一致是一致的,我们不必再用复杂的装箱算法去节省贴图空间,改用等宽登高的固定大小矩形区域切分贴图,更容易做到灵活管理。 最终设计的管理器的 C API...

游戏 UI 模块的选择

在游戏(包括引擎)开发的过程中,谈及 UI 模块,通常所指有二: 开发工具所用到的 UI 。 游戏本身所用到的 UI 。 这两者很多时候都是共用的一个模块,比如之前的 Unity 就直接把引擎开发用的 UI 模块扔给开发者开发游戏使用。但很快,开发者就发现,适合工具开发的 UI 模块,在做游戏时就不那么顺手了。所以就有了第三方 UI 插件的流行,以至于最后又倒逼 Unity 官方重新制作游戏 UI 模块。 开发工具面临的需求和游戏场景面临的需求很不一样: 开发工具需要的时候更好的将内部数据以可视化方式呈现出来,供用户浏览和修改,以适应数据驱动的开发。UI 的呈现需要的一致性,风格统一有利于减少学习成本,同时需要清晰的表达复杂的数据结构。有时还需要将内部数据的变化过程同步的动态呈现,给开发者更直观的感受。...

skynet 并发模型的一点改进思路

skynet 的内核是一个多线程的消息分发器。每个服务有一个消息队列,任何服务都可以向其它任意服务的消息队列投递消息,而每个服务只可以读自己的消息队列,并处理其中的消息。 目前的工作原理是,在任意消息队列不为空的那一刻,将该消息队列关联的服务对象放在一个全局队列中。框架启动固定数量的工作线程,每个工作线程分头从全局队列中获取一个服务对象,并从关联的消息队列中获取若干条消息,顺序调用服务设置的回调函数。如果处理完后消息队列仍不为空,则将服务对象重新放回全局队列。 这样,就完成了尽量多(远超过工作线程数量)的并发服务的调度问题。 我这些年一直在考虑这个模型可否有改进之处。能不能设计得更简单,却还能在简化设计的基础上进一步提高并发性。同时,还可以更好的处理消息队列过载问题。 ...

内存块对象的 Lua 封装

最近给 bgfx 的 lua binding 做了一点改进,因为修改了原有的 api 语义,所以需要做一点记录。 对于 3d 库来说,API 涉及大量的内存块的操作。创建 Buffer ,贴图,shader ,都需要输入一个数据块。大多数数据块是只读的,少部分是需要回写的。对于只读数据块,封装层可以用 lua string 替代,可写的用 userdata 。 bgfx 自己抽象了一个叫做 Memory 的结构,用来统一描述这类内存块对象。按 bgfx 的定义,Memory 的构造由用户决定,而释放通常由 bgfx 管理,而非调用者。 即,用户负责构造出 Memory 对象,将数据拷贝进去,然后再传递给 bgfx 的 api 后就可以撒手不管了。但是,如果你构造出 Memory...

层次结构和状态继承

在 blog 上,我写过好几篇关于场景管理模块的树结构的文章。这些也是我这两年在做游戏引擎中对象管理的思考历程。 通常游戏引擎中会把可渲染对象以树结构储存,这是场景管理模块最常见的作法。顺便说一句,GUI 界面也是用类似的方式。但是,我始终认为,从 gameplay 的层面上来看,游戏逻辑需要关注的对象并不需要用层次结构的方式管理。因为,空间结构上的层次很可能发生变化,从而引起关注的对象的层次路径变化。我们最终关注的那些东西不变,但它们在空间中的位置却会经常改变。 我一直在思考的问题是:为什么一定要用树结构组织可渲染对象?树结构到底带来了什么好处? 最直接的好处是,减少矩阵运算的次数。因为,渲染层最终需要对象在整个世界中的位置,而每个被渲染的部件本身却是逐级组合起来的(为了减少数据重复,我们不能因为一个部件换了个位置,就复制一次),部件只会记录相对整体的一个局部空间变换。如果我们平坦的保存没有可渲染部件,势必在计算它最终被渲染到屏幕时的世界矩阵的时候,需要连乘一长串局部矩阵。而组织成树结构,以一定的次序计算,可以大大减少最终矩阵乘法的数量。...

lua hash 函数的一点讨论

最近一段时间,lua 的邮件列表中有好几个主题讨论 hash 表的设计。我读下来受益匪浅。比如 前两周的这个主题 中,有同学主张去掉 lua hash table 中的链表指针,而改成固定步长的冲突链表。具体这里就不展开了,有兴趣的同学可以自己看。 这两天的讨论是围绕 lua 的 hash 函数的,暂时还没有固定链接,我把我的理解和思考记录下来,不一定正确,如有行家发现错误,请不吝赐教。 unsigned int luaS_hash (const char *str, size_t l, unsigned int seed, size_t step) { unsigned int h = seed ^ cast_uint(l); for (; l >= step;...

Discover, share and read the best on the web

Subscribe to RSS Feeds, Blogs, Podcasts, Twitter searches, Facebook pages, even Email Newsletters! Get unfiltered news feeds or filter them to your liking.

Get Inoreader
Inoreader - Subscribe to RSS Feeds, Blogs, Podcasts, Twitter searches, Facebook pages, even Email Newsletters!