Our MMO currently utilizes UNET and we’ve been eyeing ENet as a replacement but your solution is sounding very appealing. Would you use the analogy that LLAP<–>ENet and HLAPI<–>ScionNet? Looking forward to your release!
The first one is correct. The ENet is used as a transport module and shuttles packets across the network at low-level. But the programmer can replace it with any other networking library in less than an hour.
The second is very different. Instead of trying to solve everything for the programmer via attributes, codegen, and components, the ScionNet offers modules with an intuitive, clean API. Using these modules, the programmer can create a logic for the multiplayer game in a few hours and automatically benefit from the concurrency, data management, and other stuff under the hood that leads to high-performance and low-latency.
I’m planning to cover in a series of video tutorials how and where the programmer can involve each module and how to make them work in harmony with specific game mechanics. This system is user-friendly, and it’s shaped into a form of how I see modern networking backend right in the Unity environment where 90% of your code sitting in the main thread.
Ah I see sounds good. I’m not afraid of getting my hands dirty if it gives us more refined control and is less error prone!
Great stuff @nxrighthere .
What does the interface look like for sending messages to an existing framework that has it’s own concurrency model? Is it just here is the message in whatever async context your system has, and you do what you want from there? (which would be fine with me).
Basically, it’s just a method that we call after obtaining a reference to the core class and initialization. For example, let’s say that we want to send a message to a peer and we have an array with serialized data of a typical MessagePack/Protobuf class. We call the send method in the core that expects destination peer, message ID, an array with serialized data, a flag with delivery type, and channel ID (everything is almost like with the ENet). As soon as the send method is called, the life-cycle of the message looks like this:
Synchronously (the call of the send function comes from the main or any other thread/task/job):
- Acquire segment in a concurrent pool for the send function (essentially this the segment of a self-stabilizing circular buffer that’s used as a storage for class instances with data of function calls).
- Clone an array with serialized data using rented buffer from a buffers pool and put the reference to it with other function-related stuff into the acquired segment.
- Enqueue function call into a concurrent circular queue (this is the disruptor-like Ring Buffer, we have one for events and one for functions).
Asynchronously:
- Check for any functions in the circular queue.
- If we have something there, let’s try to process as many functions as possible depending on time window between calls to the queue functions by producer and consumer.
- If the consumer successfully dequeued the send function call, create a packet for the message, send it to the designated peer, return the rented buffer back to the pool, and release the acquired segment.
@nxrighthere your solution sound very appealling your videos shows how stable the system is, no lag, no ridiculous memory consumption and memory doesn’t increase over the time. I do wish you to finish ASAP :):):).
Are you using Enet-Csharp or it’s just based on native Enet library.
Thank you. Yes, the transport module is the ENet-CSharp, but it was slightly changed for this system.
Great!
Hi there. Do you plan to do a benchmark of your C# wrapper of Valve’s networking?
It would be nice to see the results on your machine.
Yes, I mentioned this some time ago:
I’ve described the problems here with the library. It’s still not fixed.
Oh. Sorry about that.
Thank you.
Hi I’m analyzing the best approach to implement a mobile MMO with simple physics on a 2d world for around 100 players together and this post is helping me a great deal.
I read through (most of) this, and I’m not sure if there’s any reason not to include SpatialOs in the benchmark. I thought it seems a good option, but maybe a I’m wrong.
At this very moment I was thinking about using ENet. If possible I’m searching for a solution that would require just quick adjustments on server side, to let us focus on client side. Any suggestion is highly appreciated.
I’m not sure about the mobile platforms it’s not my area, unfortunately. But on the desktop, with my concurrent networking system using ENet, I’m running high-load simulations with low resource consumption and everything works without any problems.
I’ve recently made simulation tool for it using the same technique that I use in the BenchmarkNet where’s each client is an asynchronous task and here’s a demo with 128 clients, 20 state updates per second each, right in the Unity environment on AMD FX-4300 (4-core 4GHz): https://a.doko.moe/mtybzt.mp4
The biggest consumer of CPU power on this video is Unity’s built-in physics. In this demo, I’m using a single-producer single-consumer pattern, but the system has other several options that allow you to have multiple producers and consumers with any number of threads you want.
[Here]( Garbage Collector API page-2#post-3743614) you can read what I’m using to minimize GC influence.
@Jack-Mariani and thank you for your contribution on Bountysource, Jack, I appreciate that. ![]()
If you are going to write high-level stuff for the game by yourself, you can use any networking library from the list on the first page. With any of those libraries, you can prototype client-server logic and make some adjustments in no time. All those libraries can handle 100 clients per server instance with a reasonable amount of data for transmission, but GC is the biggest problem of the managed libraries, especially in Unity.
If you are looking for something like HLAPI, I don’t recommend anything for many reasons (unnecessarily overcomplicated inefficient design and so on).
Hey @nxrighthere , we noticed that you included TCP on your Wiki page now. Will you ever publish the Telepathy results?
You are the only person who took the time to benchmark networking libraries for Unity and people got immense value out of it. We are all counting on you, and a scientifically correct benchmark shouldn’t omit results based on personal preference, etc. Let the people draw their own conclusions ![]()
BenchmarkNet 2.0 is not finished yet, and in the current state, I can’t add any TCP library. Nanomsg, NetMQ, Telepathy, it doesn’t matter. If you add UDP support like how DarkRift does, I’ll integrate the library into the application on the next day, since the unreliable protocol will be available and we can compare things relative to the other libraries.
Hello nxrighthere
Can you say something about TNet?
I am surprised that there is not benchmark result for TNet, this is a hidden gem in my opinion. Do you have a plans to test it?
TNet have some very unique and powerful features, so I would like to see an opinion of professionals in network technologies about TNet.
@nxrighthere got an ETA on the release of ScionNet? ![]()
Are you accepting beta testers?
Hopefully two more weeks from now (fingers crossed). I finished working on compression module for floats, vectors, and quaternions + I’ve integrated LZ4 at packet-level into ENet, you can read here about it. Now I’m working on AoI logic for network culling which should work in .NET Core and Unity as other modules. When I’ve done with the culling module, I’m planning to release ScionNet, and then start working on vectorized buffers cloning, server instances orchestrator, and other stuff.
As for beta testing, I already have a few guys they are work with me. ![]()
By the way, it seems that I found a very critical bug in Unity where’s memory barriers fail in some cases, even if you are using built-in concurrent collections (I don’t use them). I’m creating a test case for this issue right now.