handling player numbers in a gameworld?

Started by
8 comments, last by hplus0603 3 years, 4 months ago

I have been writing a browser-based multiplayer game that I'm running off a home-built socket server using socketIO and threejs. In the game there is a finite number of rocks that players can pick up and build into 'cairns' (they're a kind of trail-marker), the players can see each other moving around in the world. The idea is that the positions of the rocks persists until somebody else moves them, so that new players see the markers left by past players.

screencap of the gameworld, player avatar in center

This is all working and stuff, but I have hit a problem. What happens if loads of people were to enter the world at once? The socket server can probably deal with quite a few players, but the client browser will definitely hit a limit pretty fast where it struggles to render and update a lot of avatars in the world.

After a bit of research, seems the most obvious solution would be to create 'rooms', so that when too many players fill one instance of the world the server just makes another instance and starts putting players in there. But in my game this creates a problem, each room is sort of a ‘parallel universe’, so when it comes to the rock positions how do you merge them back so that the rocks are in the right place for people in world A and world B? I don't think you can.

The only other idea I had was just to make a queue so that if the world is full, new players just have to wait. But that's a pretty discouraging solution for players. My question is what other ways are there of dealing with player numbers in an open-world of which there can only be one instance?

There is a possibility that this is a game-design problem and I should've thought about the implications of the rock mechanic before I started coding it…oops

None

Advertisement

At some point, you just run out of oomph. There's no other way around it. Resources are finite, thus, you have to be prepared to either limit the number of players (with a queue) or create multiple, parallel, worlds.

That being said, you can raise the number of people in a world through a number of tricks. If the main challenge is rendering other players on the clients, how about rendering just the nearest 20 players? Maybe you can render a simple cutout of a gray person for players that are further out than that? That would let you get a lot further.

Of course, players will figure this out and try to all pile into one big dogpile, and at that point, nothing works. Older MMOs used things like “portal storms” that would teleport players randomly to other areas of the map. Newer MMOs I think just let the client lag, and the people with the slowest clients and least tolerance for lag will give up first.

enum Bool { True, False, FileNotFound };

@hplus0603 hey, thanks for the reply!

yes, I thought that just culling the view would be a good bet, I'm going for a dark, misty forest vibe anyway so it would work aesthetically, but got stuck at the realisation that players will pool into one place. I didn't know about the “portal storms”, that's a really cool idea and quite an elegant solution to the problem.

I suppose if one had various entrances and exits to different areas of a world, you could block one off by a fallen tree or a pile of rocks whenever that area becomes to full. You might be able to hop off something to get out but it's not possible to get in until the fallen tree or whatever is cleared by enough people leaving. Could be nice to have the player distribution balanced by ‘natural’ phenomenon like this….

None

Some games just have each server / “room” be it's own persistent thing. Player characters generally just can not transfer between them freely and would have picked one with space when they created the character.

Others like EVE Online run a single persistent universe but is actually split into separate areas players can travel between (e.g. systems with gates between). While generally movement between them is free, there is actually a population cap that will prevent the transfer / “jump” if the target system is full since they can't handle all the players going to one area (both server resources and client limitations I suspect)

stickyvectors said:
My question is what other ways are there of dealing with player numbers in an open-world of which there can only be one instance?

Surprised h+ didn't mention these two: Interest management is probably the biggest tool available for bandwidth and communications. Spatial hierarches like quadtrees/octrees, BSPs, or similar can reduce processing load on clients and servers. Both are commonplace.

Interest management is about understanding what is important. The server shouldn't send everything to everybody, since presumably people are generally spread out. Instead, the most interesting things should be transmitted, with frequency and priority based on how interesting it is, and the rest ignored.

Typical interest management has zones based on location. There is the zone of what is immediately around you, a circle which is at least minimally interesting. That needs to get transmitted eventually but can be low priority when nothing else is happening at higher priority. Then there is content in the viewing frustum, stuff you can see that is farther away may be medium priority, elements very close to you are high priority. A few items that are not visible may also be of some priority. Everything else is not a priority and really doesn't need to be updated. There are plenty of implementation details, but that's the overview. It requires a little more overhead on the server to track what each client actually knows about, but the overall processing and bandwidth load are typically dramatically reduced.

Spatial hierarchies help solve the n-squared communications problem. Instead of items needing to broadcast everything to every other player/object, they can limit it only to the items nearby. While updates still may require a few communications to neighbors, it is far less than communications to the entire world.

This can still break down when lots of people or objects are clustered together, and in those situations look for alternatives. Is it okay to only load N of them? Once it gets full enough can you update them less frequently, such as a round-robin fashion in rotation? Should the system enter a slow motion mode, or perhaps allow those with more bandwidth to work at higher resources?

Ultimately every system will hit maximum limits, but a world like you described on modern connections can typically support a hundred or so concurrent players with good interest management without too much difficulty.

@frob This is very detailed and extremely helpful, thank you!

I had not heard of interest management as a concept, although the basic principle seems quite simple. At the moment I have decent headroom on the server side, so this strategy should at least help streamline things. I reckon I can use some THREE.js code on the server to measure distance between vectors and then only tell players about other players near them. Should be grand :D

None

Interest management is probably the biggest tool available for bandwidth and communications.

Mainly because most actual games these days will choke on the n-squared player-physics problem, before they choke on the n-per-player player update problem, which is only an n-squared problem at the server end, and servers have oodles of bandwidth in modern systems. 15 years ago, bandwidth management was still quite important. These days, the games with most bandwidth problems are minecraft/roblox type games that need to send large, user-updated levels in real time.

I reckon I can use some THREE.js code on the server to measure distance

Beware, though: using JavaScript for your server isn't great – it's single-threaded, and it's bad at real-time networking, and it's garbage collected in a way that can easily decide to stop-the-world for a bit to collect garbage. Also, “measuring distance between players” is not something you necessarily need a library for – it's Pythagoras, perhaps extended to 3D (which is still just root-sum-square of coordinate differences.)

enum Bool { True, False, FileNotFound };

@hplus0603

Beware, though: using JavaScript for your server isn't great

Ah, yes, fair point. In which case, do you have a recommendation for a server-side language that would be more suited to this kind of application?

Also, “measuring distance between players” is not something you necessarily need a library for – it's Pythagoras

Haha, oh yeah! Math's has never been my strong suit…I didn't even think of that!

None

Server languages:

For servers, any language with garbage collection will end up causing pain that's hard to mitigate for a real-time system. That leaves us with the old-school languages (C, C++) and the newcomer Rust. (There are people who will point out “real-time incremental GC” type implementations, none of which are really a thing in an actual reasonably accessible development environment.)

That being said, for a first project, “getting the game done and shipped” beats everything else. It's better to have a game with occasional glitches, than not having a game at all, so don't let me discourage you from the current effort – more like putting up a flag for what to look for, and what you're going to have to work on if you get successfull (a good problem to have :-D)

enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement