(如果只是幽默的心理形象,您可能想知道“猴子打补丁”或“鸭打孔”一词。)
除此之外:如果您的目标是减少“行为”更改的迭代时间,请尝试一些可以最大限度地帮助您解决问题的方法,并很好地结合起来以在将来实现更多功能。
(这会有点切线,但是我保证它会回来的!)
- 从数据开始,从小开始:从边界(“级别”等)重新加载,然后逐步使用OS功能来获取文件更改通知或定期进行轮询。
- (有关奖励积分和较低的加载时间(再次减少迭代时间),请查看数据烘焙。)
- 脚本是data,它允许您迭代行为。如果您使用脚本语言,则现在具有通知/功能,可以重新加载这些脚本(已解释或已编译)。您还可以将解释器挂接到游戏中的控制台,网络套接字等上,以提高运行时的灵活性。
- 代码也可能是数据:您的编译器可能支持overlays,共享库,DLL等。因此,您现在可以选择一个“安全”时间来卸载和重新加载手动或自动覆盖或DLL。其他答案在这里详细介绍。请注意,此方法的某些变体可能会与加密签名证明,NX(无执行)位或类似的安全性机制混淆。
- 考虑一个深版本的保存/加载系统。如果即使面对代码更改也可以稳健地保存和恢复状态,则可以关闭游戏,并在同一时间使用新逻辑重新启动游戏。说起来容易做起来难,但是它是可行的,并且比通过调用内存来更改指令明显更容易,更可移植。
- 根据游戏的结构和确定性,您可能可以进行录制和回放。如果该记录刚好在“游戏命令”上(例如,打牌游戏),则可以更改所需的所有渲染代码,然后重播该记录以查看所做的更改。对于某些游戏,这就像记录一些开始参数(例如随机种子)然后进行用户操作一样“容易”。对于某些人来说,要复杂得多。
- 努力减少编译时间。与上述保存/加载或记录/回放系统结合使用,甚至与覆盖或DLL结合使用,与其他任何事情相比,这可能会减少周转时间。
即使您没有完全重新加载数据或代码的方式,这些观点中的许多观点也是有益的。
支持轶事:
在大型PC RTS(约120人的团队,主要是C ++)上,有一个非常深的状态保存系统,该系统至少用于三个目的:
- “浅”保存不是馈送到磁盘,而是馈送到CRC引擎,以确保多人游戏保持锁步仿真状态,每10-30帧一个CRC。这样可以确保没有人作弊,并在几帧后捕获了异步错误
- 如果并且当发生多人游戏同步错误时,每帧都会执行一次超深度保存,然后再次馈送到CRC引擎,但是这次CRC引擎将生成许多CRC,每个CRC用于较小的字节批处理。通过这种方式,它可以准确地告诉您状态的哪一部分已在最后一帧内开始偏离。我们发现使用此处理器的AMD和Intel处理器之间存在令人讨厌的“默认浮点模式”差异。
- 常规的深度保存可能不会保存例如您的单元正在播放的动画的确切帧,但会获取所有单元的位置,运行状况等,从而使您可以在游戏过程中随时进行保存和恢复。
从那以后,我就在DS的C ++和Lua纸牌游戏上使用了确定性的记录/播放。我们加入了为AI设计的API(在C ++方面),并记录了所有用户和AI动作。我们在游戏中使用了此功能(为玩家提供重播),但也可以诊断问题:当发生崩溃或异常行为时,我们要做的就是获取保存文件并在调试版本中进行播放。
此后,我还多次使用了叠加层,并将其与“自动抓取该目录并将新内容上传到手持设备”系统结合使用。我们要做的就是离开过场动画/关卡/所有内容,然后再返回,不仅将加载新数据(子画面,关卡布局等),而且覆盖层中还将包含任何新代码。不幸的是,由于复制保护和专门处理代码的反黑客机制,对于最新的手持设备而言,这变得越来越难。不过,对于lua脚本,我们仍然这样做。
最后但并非最不重要的一点:您可以(而且在各种非常小的特定情况下,我也可以)通过直接修补指令操作码来进行一些麻烦。但是,如果您使用的是固定平台和编译器,则此方法效果最佳,并且由于它几乎无法维护,非常容易出错,并且难以快速完成工作,因此我大多只在调试时使用它来重新路由代码。但是,它确实使您很快了解了很多有关指令集体系结构的知识。