1 抽象
这篇文章主要阐述一种 角色实体(本体/克隆体)持续主动读取公共数据,并根据这些数据自动作出响应 的程序思想。
这种思路有别于传统的 角色实体内部程序自我驱动 方案,使程序系统控制权更加集中,有利于前后端分离和模块间解耦合,一定程度上可提升程序的稳定性、易用性、易拓展性、易维护性。
2 传统的方案
传统的方案给予角色实体很高的自主权力,包括但不限于(设有 等待 延迟的)自主显示、隐藏、移动、操作变量、列表等能力。
2.1 由广播驱动的
以游戏中的轻量提示消息(Toast)为例,其传统的实现方式如图 2.1:
- 接收请求消息的广播
- 读取消息请求信息并作出响应(如切换造型)
- 主动显示(包括动画)
- 主动等待
- 主动隐藏(包括动画)
这样会导致一些问题:
- 难以中断:如果想要从这个角色外打断这段程序(包括等待和动画),则只能在这段程序中额外加入判断,或在这个角色实体内另外设置用于中断这段程序的程序(比如一段 当接收到“中断”广播时 停止这个角色内其他脚本 的程序);
- 稳定性弱:短时等待可能会由于 Scratch 特性原因出现误差,导致意外;
- 广播危机:如果项目中存在大量类似模块,则需要创建大量广播对这些模块进行控制,以保证各个模块间的运行相对独立,互不干扰。同时,这也需要另外设置判断决定是否执行广播,否则很容易会出现克隆体接收广播后创建更多克隆体的 克隆体溢出事故。
2.2 由自己驱动的
以游戏中玩家控制的主角为例,这个主角可以移动和缩放自身大小,其程序结构大概如图:
这样会导致一些问题:
- 重复响应:在创建有多克隆体的情况下,可能会出现一次操作多个响应的情况。如 按下空格后变量增加 1,但是创建了 10 个克隆体,于是这个操作被响应了 11(克隆体和本体)次;
- 程序糅合:由角色实体自行更新数据并作出响应,会导致程序中外观、运动代码与数据(变量、列表)混合,使程序复杂,增加了阅读、理解的成本;
- 控制权复杂:这样的结构意味着大量的数据同时被大量的角色实体控制着,这会导致 数据变化难以追踪、溯源,在出现异常数据时寻找原因很容易变成大海捞针,为迭代更新和 Bug 修复带来棘手的麻烦。
2.3 小结
总的来说,以上所呈现传统方案的核心问题在于 前后端(简单理解即数据和 UI)杂糅 和 模块的强独立性。
这会导致各个模块像一个个孤岛,各个五脏俱全、各司其职,但是缺乏统一调度,容易冲突、混乱。
由此出发,大型项目亟需一种更加合理的系统结构,以保证其开发、维护的效率和运行的稳定性。
3 由数据驱动的方案
这个思路的核心是 前后端分离 和 前端主动响应。
这个思想包括一个(组)只负责处理数据的角色(后端操作)和一个(组)只负责响应数据的角色(前端响应)。
3.1 角色控制案例
角色控制的后端操作程序案例如图 3.1:
其前端响应程序案例如图 3.2:
3.2 Toast 消息案例
值得一提的是,这种思想也使得 Toast 变得更加灵活,程序案例如图 3.3:
图 3.3 中的程序满足我们所预想的 便捷调用 和 便捷打断 要求:
使用的时候,通过 设置 TOAST 变量(公共、对外暴露)为文字 来触发并调用造型为 TOAST 变量 所指定的 Toast 消息,
并且可以随时随地将 TOAST 变量设置为 0,以终止当前正在进行的 Toast 显示任务。
3.3 小结
总的来说,由数据驱动的程序系统通过 让前端主动响应数据 实现了 前后端的有效分离、通过 对外数据接口暴露 实现了 模块的随处便捷调用、通过 设置专门数据处理的角色(后端操作核心)实现了 项目各模块的集中统一调度。
4 与逐帧响应的结合
此外,由数据驱动的思想还有其他功效。
不难发现,文章所呈现的以上案例还结合了 逐帧响应的思想:所有前端模块的响应均由 LOOP 广播 驱动,不另外设置内部循环。
这带来了一些好处:
- 模块同步:通过广播驱动,使所有模块的运行同步,避免各自循环不同步带来的隐患;
- 可暂停:在不广播时,所有由此广播驱动的模块均会暂停工作,并且冻结在当前的状态,于是可以实现纯原版暂停;
- 高性能:有研究表明,Scratch 中的循环会影响运行效率,因此禁止各模块内部循环可以一定程度上提高项目整体性能。
5 总结
总的来说,本文所介绍的由数据驱动的程序结构具有运行稳定、易拓展、易迭代、易维护等特点,适合拥有多模块的大型项目使用。
但是同样不可忽视的,还有这个结构自身可能带来的额外的 复杂度 :在编写应用了这个思想的程序时可能会需要一些 思维上的转变 或 额外的积木,在开发新模块时也许会降低早期开发的速度。
6 后话
这个思想是经过验证的,上次 Liny 参加 Game Jam 的项目《鹅》和这次的《馋猫》都应用了这个思想,结果就是它带来了更少的 Bug 和更高的 Debug 效率,以及纯原版暂停等诸多有用特性。
如果你有兴趣,可以试试实践这个思路,甚至进一步改进它,以实现更高效的开发和更稳定的运行。
如果你有一些新发现,也请拜托告诉 Liny,这样 Liny 也能学到新东西,然后继续修缮这套系统。
最后的最后……祝大家 Game Jam 顺利(?
= ̄ω ̄= 要睡了(((2024年8月3日 03点37分
这次的文章没有内审,可能有错字(*
嗯
嗯嗯,有道理学到了
好像不是awaliny本人发的))
沙发~