我建议像使用 NodeJS 一样为您的游戏创建自己的服务器。我所知道的大多数解决方案都很难使用,并且无法完成您想做的所有事情。
例如,暴雪游戏的《炉石传说》的客户端是基于Unity的,并且有一个定制的服务器端。
以下是有关如何创建游戏服务器的一些建议。
在物理部分出现之前,它似乎工作得很好:当客户端说有东西被击中或爆炸时,服务器必须信任客户端,然后将其广播给其他客户端。
创建服务器时,您必须在服务器端而不是客户端做出每个重要决策。
聚会是由服务器发起的,所以服务器必须有以下信息
- 地图大小
- 玩家人数
- 每个玩家的数据(生命值、位置、体型、攻击速度......)
- 做出决定所需的任何其他信息
现在,客户端应该始终向服务器发送非常小的信号,如下所示
- 向左移动
- 加入派对
- Shoot
- 右旋
- etc...
基于用户的操作和用户的数据,服务器可以运行游戏的“模拟”。
- 检查该操作是否被允许
- 如果允许的话,模拟这个动作。如果不是,则将其放入队列中
- 向用户发送有关正在发生的事情的信息(玩家一击中,玩家二死亡,玩家四左移动等......)
这样,服务器就知道什么时候发生了事情并决定发生什么。您不依赖客户端信息,您只收到玩家想要的操作。
但是,正如您所说,由于延迟和其他网络因素,您的客户端不能过于依赖服务器。在现代游戏中,客户端拥有与服务器相同的玩家数据,并且并不总是依赖服务器在屏幕上显示正在发生的事情。
如果您玩过一些在线游戏,您可能已经注意到,当与服务器的连接丢失时,您有一小段时间可以继续玩(移动、射击等),但除了您之外,没有任何东西会移动。
这是因为即使没有服务器信息,客户端也会根据您的操作继续“运行”游戏。
然而,为了避免客户端向玩家显示的内容与服务器模拟中发生的内容之间存在巨大差异,客户端和服务器会定期“同步”。
例如,如果您决定向左移动,客户端知道您的移动速度,因此可以在不依赖服务器的情况下显示移动情况。
当同步发生时,服务器向客户端发送关键信息,并且客户端用服务器发送的内容更改任何当前显示的信息。
以左移动为例,如果您在服务器和客户端上的移动速度不同,当客户端收到同步命令时,您会注意到您的玩家将从显示的位置“传送”到另一个位置。如果某些数据包丢失或由于高延迟,也可能会发生这种情况。
在服务器和客户端创建在线游戏时,处理延迟是一个巨大的挑战,这不是本问题的主题。
总而言之,您的服务器应该
- 自制的
- 只接收来自客户端的操作
- 模拟游戏
- 向客户发送有关正在发生的事情的信息
- 定期与客户端同步
希望这有帮助=)
Here are some explanation on how to add logic inside your server.
Small disclaimer before, I've never used NodeJS so I don't know if this is achievable using NodeJS, I usually use C++.
现在,对于您的游戏,我假设玩家只能使用“移动”动作。
当用户连接到您的服务器时,您可以启动游戏。
因为你的用户可以移动,这意味着有一个 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
在服务器端拥有您的新职位。如果这个位置在地图的边缘,你有两种选择,让用户出现在地图的另一边缘,禁止该动作。
您的服务器会定期向客户端发送玩家的当前位置。