在游戏相机中

游戏中良好的摄影机实现非常有趣,通常会向玩家隐藏很多细微之处,以便呈现最佳的动作视图。 不相信我吗? 看看《超级马里奥世界》中某些摄像头模式的快速介绍。

由于相机是一种很好的运动方法(我的几个学生最近都在问这个问题),所以我想我很快就会谈论我对我的工作。 可能值得一提的是,这非常简单,因此对于经验丰富的开发人员而言,本文内容不太可能包含任何惊喜。 希望如果您只是开始考虑这些东西,它仍然会有用。

我当前项目的灵感显然是早期的《塞尔达传说》游戏,但是与3DS和3D以及“现代”硬件相比,在3DS上链接世界之间可能是最好的选择。

塞尔达(Zelda)类型的相机实现具有谨慎的模式,具体取决于玩家的行为/所在区域的游戏类型。 您可以将主要的粗略列出为:

  • 自由跟随 :相机将跟踪地面高度,并尝试向玩家的行进方向前方移动,以便他们可以更好地看到前方的事物。
  • 锁定跟随 :类似于自由,除了地面高度将被忽略。 考虑一下具有多个高度平台的地牢房间……根据游戏玩法,相机的高度可能会固定在这些位置, 也可能不会固定。 但最常见的是固定在一个高度上。

这两种模式都可以限制在一个区域内。 IE:摄像机运动将被限制在预定范围内。 这在“地下城”中最明显的地方,即您在两个房间之间进行过渡-摄像机直到您穿过一扇门后才会向您显示下一个房间-但在室外区域也是如此。 您通常会(通过强制滚动)从林木区域过渡到“村庄”或类似的地方。 我将在游戏中做同样的事情来掩盖室外区域之间的关卡流。

  • 焦点 :玩家已经与一个对象进行了交互,并且/或者正在进行对话,因此相机将焦点从屏幕中心移到对话框上方的区域。 或者,从其领先位置追溯以重新专注于播放器。
  • 战斗 :类似于“焦点”,但跟踪玩家和他们锁定的对象,并优先考虑锁定目标的位置。
  • D-Pad超越 :在以下模式下-可能是战斗,我需要检查-玩家可以使用D-Pad手动移动相机,但放开后它将反弹。 这也受区域限制,具体取决于位置。

您还可以争辩说,这些模式的进出状态也是需要处理的谨慎状态(它们将在代码中),但是为简单起见,我将跳过这里的内容。

我编写此摄像头系统的第一步是将摄像头逻辑大致按照上述步骤分解为状态机,并开始构建功能。 这是一个错误。 这使我走下了将每个谨慎的摄像头模式编写为自己的“子”状态机的道路,这一切都过于复杂了。

我迅速将其丢弃,并以最简单的状态重新开始:

我们在这里想要做的主要事情是“领导”玩家-确保摄像机位于玩家前方,以便向他们显示更多的前进方向。 这表示:

  • 摄像头的移动速度必须比播放器快(因此可调节的物体会在此处曝光)
  • 需要定义(观察到的)相机可以超越播放器的距离(可以调整)。
  • 摄像机需要知道玩家角色向哪个方向行驶。

注意第三点。 我们不想知道角色在做什么,我们不想知道玩家的意图。

如果将摄像机以某种方式附加到角色在世界上的旋转,则可能会感到时滞。 角色不会立即从一个方向“翻转”到另一个方向。 相反,它(很可能)将旋转几帧以使眼睛看起来更平滑。 就移动角色而言,这种平滑处理是可以接受的,但随着旋转,它会使摄像机产生较长的缓慢弧度。 这可能看起来是错误的,并且绝对感到不可思议。

获得玩家的意图就像读取当前的摇杆输入一样简单。 这为我们提供了方向向量,可以对其进行归一化,然后乘以所需的任何距离。 结果(添加到玩家的当前位置时)是一个新的“想要的”位置,而没有考虑其他因素。

如果您想像这样一个想要的位置的圆圈(玩家可能朝向的每个方向,以玩家为中心),那么这个圆环代表着相机在引领玩家时可以移动的极限:

要将摄像头从当前位置移动到新的“想要的”位置,我们需要确定移动的轨迹。 我们不会一口气跳到外圈,而是一系列小步骤。

我们可以通过从摄像机的当前位置减去所需的位置来实现,这为我们提供了两个位置之间的方向矢量。

要沿这个方向矢量移动,我们对其进行归一化,然后乘以:(摄像机的移动速度* DeltaTime),然后将结果添加到摄像机的当前位置。 这给了我们预期的“最终立场”。

是的,我们制造了一种非常缓慢的寻的导弹。 简单。

现在我们有了“最终职位”,剩下的就是条件性的东西:

如果最终位置离玩家太远(在第一步中确定的环以外),则需要限制它。 一种方法是检查目标最终位置和字符之间的向量的Size(),并使用GetClampedToSize()查找外圈上的位置(如果它太长)。

如果要跟踪地面高度,则需要做出一些选择。 我们可以在摄像机和玩家角色之间使用固定的高度,但是当角色可以跳跃时,这对我来说有点不舒服。

我们可以仅从摄像机的位置进行光线投射,然后放到地面上,然后据此固定高度,但是当摄像机“掉下”玩家正在注视的悬崖时,我们将遇到很多奇怪的问题过度。

因此,相反,我选择从玩家角色向下投射光线-忽略他们是否在跳跃-并直接在其下方找到地面的高度。 新的相机高度就是这个高度,再加上一个固定的高度,但是如果世界上某些地区的坡度非常陡,这可能会引起问题。 就我而言,这不是问题,我正在创造世界,我会避免这样做,但是作为安全带和固定装置,我会在高度变化之间紧握,因此始终保持光滑。

最后要考虑的是如何处理玩家何时移动了游戏手柄上的左摇杆(为我们提供了新的想要的位置),但是玩家角色无法在世界上移动,或者角色移动得非常缓慢。 照原样站立,相机将继续以固定速度移向其外部界限,这在我的游戏中看起来是错误的。

我选择解决此问题的方法是在计算相机当前位置和新的所需位置之间的轨迹的步骤中。 与其将轨迹乘以:(摄像机的移动速度* DeltaTime),我还考虑了他们已经移动了操纵杆上的操纵杆多少,以及角色在世界上移动的速度。 看起来更像是:(摄像机移动速度*(输入点输入*世界上角色的速度))* DeltaTime

我没有提到边界检查,因为它只是一个Clamp()。 如何进入摄影机系统取决于您。 我有一个包含此数据的区域控制器,并且可以通过游戏模式来获取它。

我们还可以考虑其他一些细微之处,这取决于个人喜好:

  • 一段时间不活动后,镜头可能会从领先位置退缩到玩家角色的中心?
  • 也许播放器周围有一个小的死区,所以不是所有的动作都会迫使相机移动吗?
  • 也许摄像机在播放器后面时比在前面时移动得更快? 某种“追赶”模式。
  • 也许相机可以考虑到世界上的热点? 其他NPC或环境的某些部分可能会“吸引”摄像机引导玩家的所需位置,以指示可能值得关注的线索或区域。

我们有很多方法可以加…

如您所料,这并不是真正的特殊模式,它只是在决定我们是否要在任何给定点跟踪地面高度。 我们可以在世界范围内甚至在游戏模式级别的触发区域中执行此操作。 以我为例,我最终为地下城制作了我的相机的子类,但是主要是因为我想分开我如何在房间之间转换。 经反思,绝对没有必要这样做。

在我的游戏中,当他们处于对话状态时,我将其从播放器上移开了控制,因此主要对焦模式只是控制焦点,焦点由与之交互的对象或角色与角色之间的中点确定。他们正在与之交谈的NPC。

为了使它看起来更好,我在lerp上使用了缓和曲线。

当返回关注状态(锁定或免费)时,我无需执行任何操作。 实际上,让摄像机从原处移动而不是重新聚焦在播放器上看起来更好。 不过,我将来可能会更改此设置。

我目前还没有完成战斗,但是我打算做的方式是通过将摄像机的所需位置修改为角色和NPC之间的点,或者在NPC周围的圆上。 基本上,我希望摄像机专注于玩家正在攻击的事物,而不是玩家的角色,因此偏向NPC似乎是解决之道。 撰写完毕后,我将对其进行更新。

这很简单。 来自D-Pad的任何输入都会创建一个附加的方向矢量,作为最后一个阶段,我会将其添加到我们作为相机的“最终”跟随位置而计算出的方向矢量中。 因为D-Pad是数字的,所以我在按下按钮时向上增大该矢量的长度,在释放按钮时向下增大,以平滑其他运动。 请注意分别倾斜垂直和水平方向,以免产生奇怪的结果。

通过钳位D-Pad方向矢量的长度(这是我随时间逐渐增大和减小的固有特性),仅添加它就不会破坏任何效果。 高度不受影响,但是当推得太远时,相机可能会夹在悬崖边缘上。 幸运的是,我的世界还不足以解决这个问题,我只允许玩家手动移动相机近距离。

在对焦模式下,此替代将被忽略,因为它没有用。

请记住,这种跟随凸轮可能不适合您。 我特别模拟了一个Zelda类型的实现,它的明确愿望是引导玩家以最佳方式框架重要的事情, 而无需手动控制。

UE4有一个摄影机吊杆系统,您可以轻松地将其指向下方以避免进行任何此类工作,甚至无需将其附加到跟随世界角色的某个事物上,但是在我看来,它不会包含一些即使玩家不知道,他们也会感受到的美好。

真正的魔力在于清单上我们可以做的事情,加上这个系统(上面有一些),以及我们如何以一种流畅,无缝的方式在相机的谨慎模式之间转换。

我要留给你的😀