为 Unity 构建一个简单的在线游戏服务器

Building a simple online game server for Unity

我正在尝试为我的 Tank 游戏 2D (Unity) 构建在线游戏服务器。在我的游戏中会有2-4个玩家控制他们的坦克并互相战斗。

更新

总之,我需要一个关于我的游戏服务器的建议:

我的方向是否正确,因为某些游戏服务器服务(例如 Photon、Unity 网络)似乎并不关心如何在服务器上实现游戏逻辑。这是否使他们不是权威服务器?

我是这个领域的新手,我们将不胜感激!

资产商店中有一个名为 Photon 的资产,它是一个权威服务器。它对非移动设备也是免费的。这肯定会处理您问题的第一部分。

这个很棒的 Tutorial 会有所帮助。

我建议像使用 NodeJS 一样为您的游戏创建自己的服务器。我知道的大多数解决方案都很难使用,不能做你想做的一切。

例如,暴雪游戏的《炉石传说》客户端是基于Unity的,并且有一个定制的服务器端。

这里有一些关于如何创建游戏服务器的建议。

It seems to work fine until the physics part comes in: the server must trust the clients when they say there's something being hit or explode, then broadcasts it to the other clients.

在创建服务器时,您必须在服务器端而不是客户端做出每一个重要的决定。 开派对的是服务器,所以服务器必须有以下信息

  • 地图的大小
  • 玩家人数
  • 每个玩家的数据(生命值、位置、体型、攻击速度...)
  • 做出决定所需的任何其他信息

现在,客户端应该总是向服务器发送非常小的信号,如下所示

  • 向左移动
  • 加入队伍
  • 射击
  • 向右旋转
  • 等...

根据用户的操作和用户的数据,服务器可以运行一个"simulation"的游戏。

  • 检查是否允许该操作
  • 如果允许,模拟动作。如果不是,将其放入队列
  • 向用户发送有关正在发生的事情的信息(玩家一击、玩家二死、玩家四向左移动等等)

有了这个,服务器知道什么时候发生了什么事情并决定发生什么。您不依赖客户端信息,您只接收玩家所需的操作。

但是,正如您所说,由于延迟和其他网络因素,您的客户端不能过于依赖服务器。在现代游戏中,客户端与服务器拥有相同的玩家数据,并不总是依赖服务器在屏幕上显示正在发生的事情。

如果您玩过一些在线游戏,您可能已经注意到,当与服务器的连接断开时,您可以在一小段时间内继续玩游戏(移动、射击等),但什么都没有除了你。 这是因为即使没有服务器的信息,客户端也会根据您的操作继续"run"游戏。

但是,为了避免客户端向玩家显示的内容与服务器模拟中发生的内容之间存在巨大差异,客户端和服务器会定期 "synchronize"。

例如,如果您决定向左移动,客户端就会知道您的移动速度,因此它可以在不依赖服务器的情况下显示移动。

同步发生时,服务器向客户端发送关键信息,客户端用服务器发送的信息更改当前显示的任何信息。

以左边的移动为例,如果你的移动速度在服务器端和客户端不同,当客户端收到同步命令时,你会发现你的播放器会"teleported"从显示位置到另一个。如果某些数据包丢失或由于高延迟,也会发生这种情况。

在服务器端和客户端创建在线游戏时,处理延迟是一个巨大的挑战,这不是这个问题的主题。

总而言之,您的服务器应该

  • 自制
  • 仅接收来自客户的操作
  • 模拟游戏
  • 向客户发送有关正在发生的事情的信息
  • 定期与客户端同步

希望对您有所帮助 =)


以下是有关如何在服务器中添加逻辑的一些说明。 之前的小免责声明,我从未使用过 NodeJS,所以我不知道使用 NodeJS 是否可以实现,我通常使用 C++。

现在对于您的游戏,我假设玩家只能使用动作 MOVE。

当用户连接到您的服务器时,您可以启动游戏。 因为你的用户可以移动,这意味着有一个 2D 地图,你的用户有一个大小、一个初始位置和一个速度。 所以你的服务器应该启动一个新的 "GameParty" 并初始化上面的数据。 例如,假设设置了以下默认值。

map_width = 512;
map_height = 512;
user_width = 2;
user_height = 2;
user_speed = 1;
user_posx = 20;  
user_posy = 20;

当客户端想要移动时,他向服务器发送一个数据包说他想要移动。您可以使用任何您想要的客户端<->服务器通信协议,我使用二进制协议但假设您使用 Json

{action: move; value: left};

有了这个,你的服务器就会知道用户想要向左移动。 因此,您只需将 user_posx 减少值 user_speed 即可在服务器端获得您的新位置。如果这个位置在地图的边缘,你有两个选择,让用户出现在地图的另一边或者禁止这个动作。

每隔一段时间,您的服务器会向客户端发送玩家的当前位置。