事件的调用模式
Publish-subscribe Pattern 发布订阅模式
将已发布的消息(事件)分类为类。
接收感兴趣的消息(事件),而不知道哪些发布者
Event Definition 事件定义一般来说代码上不可能完成所有的定义,在设计层上也需要定义(可视化层反射到代码层)
回调函数是一种特殊的函数,它作为参数传递给另一个函数,并在被调用函数执行完毕后被调用。回调函数通常用于事件处理、异步编程和处理各种操作系统和框架的API。
但是回调函数使用不当会出现严重的bug,例如:在游戏对象死亡后,扣血的回调函数困难还会被调用,可以删除这个回调函数,但是困难会造成错误。
强引用的方法来解决问题,但会导致内存越来越大。
还有通过来一个判断语句来判断是否这个调用回调函数的物体,来确定是否调用这个回调函数。
Event Dispatch 事件调度
直接排发会造成要有等待上一次发送消息的时间,直接排发也会造成内存过大以及帧数过大的问题。很难实现并行化。
产生一个队列来存放信息然后在调用
环形缓冲区(ring buffer),环形队列(ring queue) 多用于2个线程之间传递数据,是标准的先入先出(FIFO)模型。一般来说,对于多线程共享数据,需要使用mutex来同步,这样共享数据才不至于发生不可预测的修改/读取,然而,mutex的使用也带来了额外的系统开销,ring buffer/queue 的引入,就是为了有效地解决这个问题,因其特殊的结构及算法,可以用于2个线程中共享数据的同步,而且必须遵循1个线程push in,另一线程pull out的原则。
线程 A 媒介 线程 B
data in --> ring buffer/queue --> data out
但是Event Queue可能会导致执行顺序出现问题,因为他是把一些信息放在一起了然后一起处理了。还有一个问题就是一般他是在下一帧才处理事件,困难在某些实时的问题上出现问题。
热跟新脚本
在游戏中会出现bug,这时候无法使用汇编等语言重新编译来解决这个bug,某些游戏设计者也不会一些高级的语言,所以会用到一种脚本语言,例如:lua。
支持快速迭代-易于学习和编写对热更新的支持
在沙箱中运行,稳定性好,崩溃少
这么工作?
脚本语言就是在游戏操作系统上跑一个虚拟机。
脚本和引擎之间的对象管理的2种方法
本机引擎代码中的对象生存期管理:
需要提供对象生命周期管理机制
当脚本使用本机对象时不安全(可能已经销毁)
对象的生存期由脚本GC自动管理:
释放对象的时间是不受控制的(由GC控制)。如果引用关系在脚本中变得复杂,那么很容易获得内存泄漏
Architectures for Scripting System 脚本系统的体系结构
把一个组件变成脚本,其实就是用引擎扩展脚本。
用脚本反过来扩展引擎。
允许在游戏运行时修改脚本
某些特定逻辑的快速迭代
允许在游戏联机时修复脚本中的错误
热更新中的一个麻烦问题
所有引用旧函数的变量都应该也要更新
使用脚本语言的缺点:
其性能通常低于编译语言。
当编译需要虚拟机运行字节码时,弱类型语言通常更难优化。
JLT是一种优化的解决方案,弱类型语言通常很难重构。
可视化脚本
为什么我们需要可视化脚本
对非程序员友好,特别是设计人员和艺术家。无错误的拖放操作,而不是代码编写。
Visual script is also a programming language, which usually needs. Variable 可视化脚本也是一种编程语言,通常需要:变量语句和表达式,控制流,功能,类(用于面向对象的编程语言)
"3C”in Game Play
角色,控制与相机就是3c系统的主要的东西。
Character
游戏中的角色,玩家和NPC。
包括人物移动,战斗,生命,魔法,他们拥有的技能和天赋等等。
人物最基本的要素之一就是运动。
control
在瞄准目标的时候一般会用到吸附系统,因为在瞄准目标的时候从信号产生到事件发出的时间过于长,所以需要一个吸附系统来实现实时的瞄准。
控制:和弦和键序列
当同时按压时,产生一个独特的游戏中的行为
密钥序列
手势检测通常由 对玩家执行的HID动作进行简要记录。
camera
复杂的效果往往是通过多个基础的调整来实现的。以创造速度感为例,我们可以做到;
在速度方向增加线
角色倒退
动态模糊
放大FOV(以加快屏幕内容的变化)