我对如何在游戏中实施重播感到好奇。
最初,我认为只会有一个游戏中所有玩家/动作的命令列表,然后“重新播放”游戏并让引擎像往常一样渲染。但是,我已经看过FPS / RTS游戏中的重放,经过仔细检查,甚至像粒子和图形/听觉故障这样的事情也是一致的(这些故障通常 一致)。
那么这是怎么发生的呢。在固定摄像机角度游戏中,我可能只是将整个场景的每一帧写入存储的流然后只是重放流回来,但这对于允许您暂停和移动摄像机的游戏来说似乎不够周围。您必须在所有时间点存储场景中所有内容的位置(否?)。因此对于像粒子这样的东西来说,这是一个很难推动的数据,这似乎是游戏中游戏性能的重要吸引力。
答案 0 :(得分:59)
我认为你最初的想法是正确的。要创建重播,您可以存储从用户收到的所有输入(以及接收它的帧编号)以及任何随机数生成器的初始种子。要重放游戏,您可以使用保存的种子重置PRNG,并为游戏引擎提供相同的输入序列(与帧编号同步)。由于许多游戏将根据帧之间传递的时间量更新游戏状态,因此您可能还需要存储每帧的长度。
答案 1 :(得分:27)
星际争霸和星际争霸:母巢之战有重播功能。匹配完成后,您可以选择保存重播以便稍后查看。在重放时,您可以滚动地图并单击单位和建筑物,但不能改变他们的行为。
我记得曾经观看过在原版游戏中播放的比赛的重播,但重播正在母巢之战中观看。对于那些不熟悉的人来说,母巢之战包含了所有原始单位和建筑物,以及各种新单元和建筑物。在原始游戏中,玩家通过创建计算机无法轻易抵抗的单位来击败计算机。当我在母巢之战中播放重播时,计算机可以访问不同的单位,它创建并用来击败玩家。因此,完全相同的重播文件会产生不同的赢家,具体取决于Starcraft播放文件的版本。
我总觉得这个概念引人入胜。似乎重播功能通过记录播放器的所有输入来工作,并假设计算机每次都以完全相同的方式响应这些刺激。当玩家输入被送入原始的星际争霸者重播时,游戏就像在原始比赛中一样。当相同的确切输入被送入Brood War重播器时,计算机反应不同,创建了更强大的单位,并赢得了游戏。
如果您正在编写重播引擎,请记住一些事项。
答案 2 :(得分:17)
有两种主要方法:
这取决于你想做什么。有时存储事件更好,因为这通常会占用更少的内存。另一方面,如果您想提供可以不同速度和不同起点播放的重放,最好存储状态。存储状态时,您还可以决定是在每个事件之后存储它们还是f.e.每秒只有12或25次 - 这可能会减少重播的大小,并使其更容易倒带/快进。
请注意,“状态”并不表示图形状态。更像是单位,资源状况等等。图形,粒子系统等东西通常是确定性的,可以存储为“动画X,时间Y:Z”。
有时重播被用作反加热方案。然后存储事件可能是最好的。
答案 3 :(得分:10)
从技术上讲,你应该把你的引擎写成确定性的,这不是随机的。假设游戏中的角色瞄准对手的手臂并射击武器,则在所有情况下都应对对手施加相同数量的伤害。
假设炸弹在位置X引爆,爆炸产生的粒子应始终产生相同的视觉效果。如果您需要随机性,请创建一组随机数,在游戏播放时选择种子值,并将该种子值保存在重播中。
一般来说,游戏中的随机性是一个坏主意。即使像多人游戏这样的东西,你也不能让一半的玩家能够看到爆炸,而其他玩家不能仅仅因为他们没有获得正确的随机值。
让一切都变得确定,你应该没事。
答案 4 :(得分:10)
鉴于初始状态和一系列带时间戳的操作,只需完成序列,因为记录的操作应该发生重播。
为了让随机事件重新发生完全相同,使用种子伪随机数并将种子 strong>保存在重播文件中。
只要您使用相同的算法从种子生成随机数,您就可以像在实时游戏中一样重新创建所有事件,而无需完整的游戏状态快照。
这将要求重播顺序观看,但这对于游戏重播来说非常正常(请参阅星际争霸2)。如果您想允许随机访问时间线,您可以以设定的时间间隔(比如每分钟)拍摄完整的状态快照,以设定的粒度跳过时间线。
答案 5 :(得分:7)
NVidia PhysX(一种常用于游戏的物理模拟引擎)能够记录物理场景的完整状态。这包含来自游戏引擎的任何驱动输入,这意味着您不需要像其他人建议的那样跟踪随机数种子。如果您进行此场景转储,您可以在外部工具(由NVidia提供)中重放它,这对于跟踪物理模型的问题非常方便。但是,您也可以使用相同的物理流来驱动图形引擎,这样您就可以进行普通的摄像机控制,因为只记录了驱动图形的物理场景。在许多游戏中,这包括粒子效果(PhysX包括一些非常复杂的粒子系统。)至于声音,我猜测它是逐字记录的(作为声音流),但我不确定。
答案 6 :(得分:4)
你最初的想法是正确的,对于真正复杂的效果,它们不会被完全记住。例如,魔兽争霸3重放系统不存储动画状态,或者在随机效果的情况下存储粒子效果等。此外,MOST事物可以从确定性方式的起点计算计算,因此对于大多数系统使用随机变量(例如,给出随机偏移的粒子爆炸),您需要的只是效果的时间和随机种子。然后你可以重新生成效果,而不必知道它最终会是什么样的......知道它正在通过一个确定的代码路径。
从概念上考虑,重播事件的时间表,您只需要用户操作。除了随机变量外,程序的反应方式完全相同。在这种情况下,您可以忽略随机性(如果效果看起来非常相同,或者它们是否可以随机重新生成,那真的很重要),或者存储种子值并伪造随机性。
答案 7 :(得分:3)
把我的两便士扔进去。
取决于你想要什么,重播可以通过
完成大多数时候,人们都希望进行互动重播,所以2.是最佳选择。然后,根据您的约束,有许多方法可以优化此过程
这真是一个引人入胜的话题。我记得原始Xbox Wreckless的一个启动标题具有良好的播放功能。不幸的是,不止一次重播会搞砸;)
是的,怎么会有人忘记Blinx Time Sweeper!将合并到实际游戏机制中的精彩互动重播!* =似乎有一些关于时间步进的评论。我在这里使用“模拟”来捕获此功能。在核心,您的引擎需要能够产生不连续的时间帧。即使重播帧的处理时间比原始帧更长或更短,系统也必须感知同一时间delta已经过去。这意味着记录每个记录输入的帧时间步长,并将此增量提供给您的引擎时钟。
答案 8 :(得分:2)
也许你可以简单地保存每个玩家发送的一堆命令。因此,您只需保存每个玩家发送的按键,而不是保存某个炸弹在某个时间点爆炸或者某辆汽车被摧毁。然后,在重播中,您只需模拟游戏,就像那些按下时一样。我觉得这有可能占用更少的空间,但我从来没有像这样的重播系统。
有趣的问题。我对它在专业游戏中的表现感兴趣。
答案 9 :(得分:2)
此外,记录随机种子不足以倒带 支持,因为随机进展不是一个可逆的过程 在依赖随机性的所有逻辑中没有特别的支持。 记录随机操作的结果更灵活 事件流的一部分。
这正是我最初的想法,当我试图弄清楚他们是如何做到这一点时,每次游戏重放总是一样的。在Doom中,我想到了拍摄的随机性:D。存储任何使用过的随机数,我发现它可能是一个解决方案。 那是在我看到关于孤岛危机技术的pdf论文之前。一些纹理在那里产生噪音,草或树的配置,似乎是使用固定可逆种子的伪随机化来制作它,所以你看到任何时候都没有看到噪音,树木和草的改变处置!
同时避免存放数百万棵树木和草井的位置。 显然,伪随机序列可以随时重放相同的内容,因为逻辑是固定的,只是制作一个假的统计随机数字序列。
答案 10 :(得分:1)
拥有一致的重播的问题与拥有一致的多人游戏一样(更好,更容易)。
正如其他人之前提到的,RTS游戏中的重放是通过记录所有输入来存储的(具有效果。滚动没有效果。) 多人游戏也传输所有输入
记录所有输入而不仅仅是猜测 - 有一个用于阅读Warcraft3重放的库,可以显示这个。
输入包含此答案的时间戳。
答案 11 :(得分:-1)
我相信在某些增量下游戏会拍摄一切状态的快照(一切)。然后,当重放发生时,可以使用线性插值的简单用法来填充“空洞”。至少这就是我认为它会如何完成。
你是正确的,记录输入是不可靠的/不保证相同的输出。游戏肯定要跟踪所有对象(或至少是重要对象)的状态