Hi, I have 10k Vector2 (array) object points in the state. For each 30 tick, I get player position and send near object points. But calculation slows down and causes a delay in the game.
How can I improve that? No need to worry real-time calculation (broadcasting after 2s 3s okay) I just don’t want to cause main-thread delay.
if (tick % tickrate == 0) { // This helps a lot but each tickrate frame my game delayed
Object.values(state.presences).forEach((p: nkruntime.Presence) => {
const nearPearls = state.pearls.filter((pearl) => {
return Math.hypot(state.positions[p.sessionId][0] - pearl[0], state.positions[p.sessionId][1] - pearl[1]) < 100;
}); // Need to calculate near objects. <<<<<<<< Any idea how to improve that without decreasing object count
dispatcher.broadcastMessage(OPCODE.ObjectPosition, JSON.stringify(nearPearls), [p]);
});
}
@emircanerkul There are a lot of different ways to solve this problem. You have N number of clients moving through the game world with K number of nearby points, and want each client to have a representation of its own and each other client’s nearby points. Is this correct?
Do you want a client or server authoritative game? This affects how we would proceed.
Have you considered representing your game world as a grid? If you have one, you can perform a breadth-first search from each player (capped to a certain distance) on your authoritative server.
Each point within a certain number of tiles in the grid near the player would be classified as “nearby”.
No, It should be fluent as much as possible. My game is 3D but I only work with 2D due to no need z-axis (no jump or fly). With the GRID-based game style, it wouldn’t fluent as I want. Objects should be able to move along the diagonal vector.
I don’t mean that the game needs to be experienced by the user as a grid. I am suggesting you use a grid “under-the-hood” and keep it in memory as a reference for your calculations.
Oh, I understand. But graph-like implementation might be hard for me. I can use caching/preventing broadcast & calculation easily to optimize for non-moving objects. Are there any other suggestions?
Also, I wonder if is there any easy solution/implementation?
Like:
Multithreading
Workers
GPU port for vectorial calculations
I also my other concern is using walletupdate in my matchLoop. I assume it will reach db and may cause performance issues. As i see nk.walletUpdate is not Promise.
Multithreading isn’t an option in the Typescript runtime but you could do it in the GoLang runtime. But that won’t change the fact that unnecessary/inefficient work is being done, even if it isn’t blocking the match loop.
Here are a few other suggestions:
(1) I don’t see why Object.values is necessary.
(2) Instead of iterating through all the presences in a loop, you could trigger only calculate nearby objects when a presence sends a move message.
(3) Instead of iterating through all the pearls, the presence could send a list of candidate pearls that have been collated on the client and then verified by the server.
I think we’ve discussed a few different approaches but it’s not an exhaustive list. Ultimately it’s up to you what tradeoffs you want to make and I think we’ve covered enough options to give you a good starting point.