代码之家  ›  专栏  ›  技术社区  ›  Steven Evers

从概念上讲,重放在游戏中是如何工作的?

  •  142
  • Steven Evers  · 技术社区  · 14 年前

    我有点好奇游戏中如何实现回放。

    在里面 一致)。

    12 回复  |  直到 12 年前
        1
  •  61
  •   Peter Ruderman    14 年前

    我认为你最初的想法是正确的。要创建重播,您将存储从用户接收的所有输入(以及接收到该输入的帧编号)以及任何随机数生成器的初始种子。要重放游戏,您可以使用保存的种子重置prng,并向游戏引擎提供相同的输入序列(与帧编号同步)。由于许多游戏会根据帧之间经过的时间量来更新游戏状态,因此您可能还需要存储每个帧的长度。

        2
  •  29
  •   Bobwise    14 年前

    星际争霸和星际争霸:孵卵大战有重播功能。匹配完成后,您可以选择保存重播以供以后查看。回放时,你可以在地图上滚动,点击单位和建筑,但不能改变它们的行为。

    我记得有一次我看了一场比赛的重播,这场比赛是在原来的游戏中进行的,但是重播是在《孵卵大战》中进行的。对于那些不熟悉的人来说,孵卵战包含了所有的原始单位和建筑,以及各种新的。在最初的游戏中,玩家通过创建计算机无法轻易对抗的单位来打败计算机。当我在《孵卵战争》中重播时,电脑可以访问不同的单位,它创建并用来打败玩家。因此,完全相同的重播文件导致不同的赢家取决于哪个版本的星际争霸正在播放文件。

    我总是觉得这个概念很吸引人。似乎回放功能通过记录播放器的所有输入来工作,并假设计算机每次都会以完全相同的方式响应这些刺激。当玩家的输入输入被输入到原来的星际争霸重放程序中时,游戏的效果和原来的比赛完全一样。当同一个精确的输入被输入到孵卵战争重播机时,计算机的反应不同,产生了更强的单位,赢得了比赛。

    如果你在写一个重播引擎的话,要记住一些东西。

        3
  •  18
  •   liori    14 年前

    主要有两种方法:

    1. 存储事件(如玩家/ai动作)——正如您所说。

    这取决于你想做什么。有时存储事件更好,因为这通常占用更少的内存。另一方面,如果您想提供可以以不同速度和从不同起点播放的回放,最好存储状态。在存储状态时,您还可以决定是在每次事件后存储状态,还是每秒仅存储12次或25次,这可能会减少重播的大小,并使重播/快进更容易。

    有时重播被用作一种防热方案。那么存储事件在这里可能是最好的。

        4
  •  10
  •   Timothy Baldridge    14 年前

    从技术上讲,你应该写你的引擎是确定性的,这是没有随机性。假设游戏中的一个角色瞄准对手的手臂,并发射武器,那么在所有情况下,对对手的伤害应该是相同的。

    一般来说,在游戏中随机性是一个坏主意。即使是多人游戏,你也不能让一半的玩家都能看到爆炸,而其他玩家则不能,因为他们没有得到正确的随机值。

    把一切都确定下来,你就应该没事了。

        5
  •  10
  •   Ben S    14 年前

    鉴于 初始状态 和一个 ,只需按照录制的动作应该发生的顺序进行回放。

    为了让随机事件完全相同地再次发生,

    只要使用相同的算法从种子中生成随机数,就可以重新创建所有事件,就像它们发生在实时游戏中一样,而不需要游戏状态的完整快照。

    按顺序观看 ,但这对于游戏回放来说是很正常的(见星际争霸2)。如果要允许随机访问时间线,可以 以设置的间隔拍摄完整状态快照 (比如说每分钟),以设定的粒度在时间线上跳跃。

        6
  •  7
  •   Dan Bryant    14 年前

    nvidiaphysx(一个经常在游戏中使用的物理模拟引擎)能够记录一段时间内物理场景的完整状态。这包含了来自游戏引擎的任何驱动输入,这意味着您不需要像其他人建议的那样跟踪随机数种子。如果您使用这个场景转储,您可以在外部工具(由NVidia提供)中重放它,这对于跟踪物理模型的问题非常方便。但是,您也可以使用相同的物理流来驱动图形引擎,这样您就可以拥有正常的相机控制,因为只有驱动图形的物理流被记录下来。在许多游戏中,这包括粒子效果(PhysX包括一些非常复杂的粒子系统。)至于声音,我猜是逐字记录的(作为声音流),但我不确定。

        7
  •  4
  •   Stefan Valianu    14 年前

    纯粹从概念上考虑,要重放事件的时间线,您所需要的只是用户操作。程序的反应方式完全相同,除非是随机变量。在这种情况下,您可以忽略随机性(如果效果看起来完全相同,这真的很重要,或者可以随机重新生成它们),或者存储种子值并伪造随机性。

        8
  •  3
  •   johnny g    14 年前

    1. 录制视频缓冲区并稍后回放,

    大多数时候,人们都希望有一个交互式的重播,所以2.是最好的选择。然后根据您的约束条件,有许多方法可以优化此过程

    • 确保系统是确定性模拟*,这样每个输入都会产生一致的预期输出
    • 确切地 稍后[使用伪随机数生成器PRNG进行播种,或使用罐装随机集]

    这真是一个引人入胜的话题。我记得Xbox的一个发布标题 Wreckless 有很好的回放功能。不幸的是,重播不止一次会搞砸;)

    Blinx Time Sweeper ! 伟大的 进入之内 真正的游戏机械师!


    *=似乎有一些关于时间步进的评论。我在这里使用“模拟”来捕捉这个特性。在核心,你的引擎需要能够产生离散的时间帧。即使重放帧的处理时间比原始帧长或短,系统也必须 感知 德尔塔已经过去了。这意味着用每个记录的输入记录帧时间步长,并将此增量提供给引擎时钟。

        9
  •  2
  •   ThirdD3gree    14 年前

    不过,这个问题很有趣。我对职业比赛的表现很感兴趣。

        10
  •  2
  •   Dave Newman    11 年前

    此外,记录随机种子不足以倒带 支持,因为随机进程是不可逆的过程 没有特殊的支持,所有的逻辑都依赖于随机性。 事件流的一部分。

    这正是我一开始想的,当我试图弄清楚他们是怎么做到的,这样游戏每次都会重放相同的画面。随着厄运的到来,我想到了射击的随机性:D。存储任何使用的随机数,我发现它可能是一个解决方案。

    同时避免了数百万棵树和草丛的存放位置。 显然,伪随机序列可以在任何时候重放,因为逻辑是固定的,只是制造一个伪随机数字序列。

        11
  •  1
  •   Franky    14 年前

    有一个一致的重播的问题是一样的(好吧,更容易),就像有一个一致的多人游戏。

    正如前面提到的,RTS游戏中的重播是通过记录所有的输入来存储的(这会产生影响)。滚动没有效果。)

    输入包括此答案的时间戳。

        12
  •  -1
  •   Bob Fincheimer    14 年前

    我相信在一定的增量下,游戏会捕捉到所有事物的状态快照。然后,当重放发生时,可以使用简单的线性插值来填充“洞”。至少我认为应该这样做。

    您认为记录输入不可靠/不能保证相同的输出是正确的。游戏一定要跟踪所有对象(或者至少是重要对象)的状态