【问题标题】:Real-time Multiplayer Game - region broadcasting实时多人游戏 - 区域广播
【发布时间】:2016-12-13 16:35:33
【问题描述】:

我正在编写一个实时多人游戏(使用 Nodejs、socket.io),我想请你帮忙优化一点。

我用 60 次/s 的更新循环和 20 次/s 的广播循环、客户端预测和插值实现了一个权威服务器。 然后,在广播循环中,我尝试了导致性能问题的区域广播。

为了简约,服务器有以下数组:

  • 玩家实体(id + 位置)
  • 食品实体(id + 位置)

让我们在服务器的数组 server.foods 中的大地图(就像 agar.io)中生成 1000 种食物。玩家只需要知道他视口中食物的状态(比如 200 种可见的食物)。因此,服务器只向玩家发送带有 200 个可见食物(id + 位置)的 一个数据包。然后,为了让服务器知道,我们将 200 种可见食物推送到 Player 对象 (player.foods) 中的数组中

但是玩家可以移动,所以必须发送其他数据包:

  • initFoods 是要初始化的食物数组(id+位置)(仅当新食物对玩家可见时:distFoodPlayer )

  • removeFoods 是要删除的食物数组(id+位置)(仅当新食物对播放器不可见时:distFoodPlayer > 600)

要了解这些信息,我会这样做:

for (var i = server.foods.length; i--;) {
    //Edit: added the next line
    if (distPlayerFood < 900) {
        var food = server.foods.entities[i];
        var inPlayerFoods = false;
        for (var j = player.foods.length; j--;) {
            if (food.id === player.foods[j]) {
                inPlayerFoods = true;
                if (distPlayerFood > 600) {
                    removeFoods.push(food.id);
                    player.foods.splice(i, 1);
                }
            }
        }
        if (distPlayerFood < 500) {
            if (!inPlayerFoods) {
                player.foods.push(food.id);
                initFoods.push([food.id, food.state]);
            }
        }
    }
});

1000 种食物和 1 名玩家的性能还可以(服务器的更新循环保持 ~58FPS)。但是对于 5000 种食物和 1 名玩家(或 1000 种食物和 5 名玩家),由于这种双循环(服务器最高可达 ~25-40FPS),性能真的很差,但带宽却被最小化了。 性能测试已在我的计算机 (localhost) 上完成。也许有了更大的服务器,我就不会有这些问题了?

你认为我的做法不错吗?你有更好的主意吗?

非常感谢。

编辑:我将代码更改为只检查不太远的食物。服务器将达到最大 ~35-50FPS

【问题讨论】:

    标签: javascript node.js performance sockets


    【解决方案1】:

    你的算法的复杂度是 O(n!),这就是为什么它会变慢大量的食物。除非您的目标是让玩家在一个大世界中移动,否则您的方法似乎很好。优化你的实现对我有用的一种方法是将你的世界分成瓷砖,每个瓷砖都包含对其中食物的引用。然后,您可以快速获取可能在范围内的食物列表,这样您就不必检查玩家与太远的食物之间的距离。

    【讨论】:

    • 分割数组。真是天才,谢谢!所以我们有玩家的视口(即 900 的半径)和一个额外的范围,可以在新食物出现在他的视口中之前向他发送新食物(取决于服务器的延迟,比如说 +100)。一块瓷砖的尺寸是 100x100,对吧?服务器将在 ~π*10² 块上循环(可能在范围内的食物列表)。更好的是,服务器可以在距离玩家 900 到 1000 像素的唯一瓷砖上循环(~2*π*10 瓷砖)以添加/删除食物
    • 您可以拥有各种尺寸的瓷砖,只要您不会错过半径内的任何瓷砖。所以 100x100 是可以的,只要你不要忘记接触视口的图块。如果您想要简单,也可以使用 450x450 的图块,这样您只需检查当前玩家的图块和附近的 8 个图块(假设您的视口半径为 900)。
    猜你喜欢
    • 1970-01-01
    • 2021-03-13
    • 2016-11-18
    • 1970-01-01
    • 1970-01-01
    • 2023-03-04
    • 2016-06-24
    • 1970-01-01
    • 2017-09-19
    相关资源
    最近更新 更多