减少nodejs游戏的滞后

时间:2018-03-31 12:29:08

标签: javascript node.js server

我创建了一个nodejs游戏。我在服务器上有一个setInterval函数,它发送播放器附近的所有对象。但它似乎并不像我在本地运行时那样顺畅。数据包有大约60个对象。这是用于发送对象并在客户端上接收它们的服务器代码。任何压缩包装或减少滞后的方法? pinka.herokuapp.com

服务器:

setInterval(function() {
    server.update();

    for(var key in sockets) {
        var socket = sockets[key];
        var player = server.players.filter(function(p) {
            return p.id == socket.id
        })[0];


        var package = [];
        var blobs = server.getNodesInRange(player.centerX, player.centerY);

        for(var i = 0; i < blobs.length; i++) {
            var b = blobs[i];
            package.push({
                x: b.x, 
                y: b.y,
                nick: b.nick,
                size: Math.sqrt(b._mass) * 10,
                hue: b.hue
            });
        };

        socket.emit("update blobs", package);
        socket.emit("leaders", server.getLeaders());

        if(player.blobs.length == 0) {
            socket.emit("dead");
            continue;
        }

        var translateX = player._centerX * player._drawZoom - player.screenWidth / 2;
        var translateY = player._centerY * player._drawZoom - player.screenHeight / 2;


        socket.emit("center and zoom", {
            centerX: translateX,
            centerY: translateY,
            zoom: player._drawZoom
        });
    }
}, 1000/60); 

客户:

socket.on("update blobs", function(data) {
   blobs = data;
});

这是整个沟通部分。

1 个答案:

答案 0 :(得分:2)

正如Jonas W.所说,问题在于服务器 - 客户端通信。 为了提高效率,socket.io的实时系统应该基于事件而不是间隔检查。

我建议你有这样的事情:

  • 客户端上,当用户移动时发出'user:move'事件。使用不必要的更新来防止过多的事件来缓解服务器。
  • 服务器上,对特定的“播放器:移动”事件作出反应。如果需要向其他玩家广播这些事件,那么实际上可以“看到”该动作的过滤器也将避免为客户提供不必要的信息。

伪代码示例:

客户端

let updating = false;
let timeout = 0;

// Assuming this function is triggered everytime the user moves (i.e. presses a key)
onUserMove (data) {
    if ('same press as before' && updating) {
        // ignore move if it's the same that has just been done    
        return;
    } else {
        socket.emit('user:move', data);

        // 'Block' the emit for same movement for 20ms
        updating = true;
        clearTimeout(timeout);
        timeout = setTimeout(() => {
            updating = false;
        }, 20);
    }
}

服务器

socket.on('user:move', (data) => {
    const dataForTheUser = processingYouAreAlreadyDoing(data);
    socket.emit('data:for:user', dataForTheUser);

    // In case there's information to be sent to every user
    const dataToBroadcast = getDataToBroadcast(data);
    const usersToBroadcast = getCloseUsers(data);

    for (let user in usersToBroadcast) {
        user.socket.emit('whatever:event', dataToBroadcast);
    }
})