I’m not an expert but some thoughts:
By what I understand of gaming networking there’s one issue that you’ll always have by using a TCP based transport, like websockets, in that it’s an ordered/synchronous transport. Sender and receiver require the message to be assembled in order and re-sending of dropped packets and such. That’s why many games use udp for transmitting changes in the world, and makes sense, because if you waste time guaranteeing the message is fully passed when it’s done it might (will be) already be outdated, so it’s better to instead be working on the news ones that will have arrived in the meanwhile.
I don’t think you can solve this with websockets but you can attenuate it I imagine if:
- You use a transport that requires less encoding/serialization (time) and produces smaller payloads (size) this diminishes the latencies because less data and time spent on marshalling it, and also if the messages are smaller then less chance of dropped packets per msg
- Using the smallest relevant unit of info you can - if still using json then trying to minimise all keys and fields - again this in terms of TCP help on the fragmentation of the packets, although it probably increases serialization overall since it has to serialise more smaller messages (which can be helped with a better transport)
- Reducing the contention point on dispatching updates (remove synchronisation of the sending of updates)
The last 2 points are relevant for this:
It then broadcasts all player positions and rotations every 100ms to all players using phoenix pubsub back to the channel in javascript land. This is so we send one large payload every 100ms rather than a bunch of small payloads all the time.
Your animation will never be more fluid than 10 frames per second, even taking out all latencies and packet dropping, although you can help by, like you said, using frame blending. I imagine that ideally you want to send updates as soon as you’re able to process them, in the smallest unit you want (I don’t know how this fares in practical terms using json, but theoretically it would be the right thing), specially because you’re already delaying the client sending the information.
To actually test this I think the best would be to deploy a version somewhere online, write some modules that create websockets and send msgs in given intervals, and time the rate and type of received messages from the server - start from a low number increasing the throughput of the spam/clients as you go. You might want to add something also server side to see how the gen_servers fare there, the least obtrusive would be to have some counters that just gets updated on each received msg and dispatched message, and when you send the “last” message just answer with their stats.
For the connections on same machine the room (genserver) is running, there isn’t probably an easy switch you can turn on. I remember (and probably still is) that when joining game servers you would pick the server you wanted, most games would give you a ping/latency reading plus number of players, type, etc. If you have somewhat static servers (or pools of servers) then subdomaining them could work, as in, the room would hold information about which subdomain points to the server it’s being hosted and when opening a socket you would use that. Other than that and for highly dynamic servers I think you would need to implement those things with help of proxies/load balancing, where perhaps your client says “I want to join this room”, and this goes to your cluster where the host that receives the request answers with information so that then the client can make a request that the lb/proxy can use to know where to connect.