I’m working on a commercial title that needs to support up to 4 players playing in cooperative mode. The game is a mix of tower defense and top-down arcade shooter. Each player controls a character that can move around and shoot with various weapons. Players must fight off waves of AI enemies.
I’m doing some early research on the best way to implement networking for my game. I have some previous experience using Unity’s builtin network API (networkviews RPCs) and my experience with them has been rather underwhelming due to the many limitations of the API and the lack of tools provided for networking. It seems that the current general consensus is to use a 3rd party library to implement networking in Unity.
Based on my game design, there are a few shortcuts that can be taken. Since it’s a coop game and I don’t plan any kind of metagame/persistence beyond a game round, cheating hacking are not a concern to me. Therefore, an authoritative server is not a requirement. My priority would be solely centered on providing a smooth and responsive multiplayer experience for each player. I would also like to have quite a lot of enemies on the map, and I’m a bit worried this might become difficult with networking.
Could anyone with prior experience in implementing shipping a networked game with Unity provide some advices/recommendation on this topic? Which network model and/or 3rd party lib would you use? How did you separate your network code from your game logic?
You might want to read this article about how Age of Empires solved their networking issues in terms of bandwidth:
Essentially: They only send input and make sure their AI comes to the same conclusions on all machines. Maybe there is a middle ground and you can update all players AIs in turns to reduce bandwidth need. Or you group them.
Aside from this, my obvious selection for networking is Photon
If you need a lobby and game rooms where you can exchange your events, you don’t have to work on the server side and do anything through the clients. If you want to expand server-side, we include the server’s logic as source and you can code in C#.
Thanks for your suggestions tobias. I was actually looking at Photon and going through the Unity client
Is the indie license per-server instance, or am I allowed to have as many instances of the application but with a cap of 50 peek conccurent users on each instance? Also, how does the server-side photon SDK interfaces with my Unity game logic? Do I need to write the game logic outside of Unity? I’m a bit confused on this point but I’m not that far into the documentation yet…
The free license is 100 concurrent users per game/application. Even if you ran a lot of machines with 100 players each, it would soon cost you more in hosting than our indie licenses for one machine with a lot of players
The server does not replicate the Unity workflow and the server sdk does not interface with the Unity client directly. You call “operations” on the server to make it do what you need. E.g. “Join” is one of those operations to get into a room. “RaiseEvent” is another operation to send some data you provide to the players in the same room.
You could write game logic “outside” of Unity and share it on both sides. If you have a world simulation, e.g. this makes sense. Still, the client calls operations on the server side and gets results for these. This is leaning in the authoritative direction. Events are created on behalf of other player’s actions (operations) and if the world simulation needs to update clients by itself.
I was wondering that as well, to me, something with a better lobbying system makes sense, but within the game I find it hard to believe Unity’s networking would be inadequate.
Was nothing really show-stopping for small-scale multiplayer, but quite a few annoying bits:
I had a bunch of issues with RPCs - for instance, you can’t target a specific subset of players to send an RPC to
back when I tried, you could not run Unity in “dedicated” mode. It seems you can do that today with -batchmode command line
almost no dev tools to support network development, like detailed profiling of network usage (beside a global kb/s meter) and simulating lag
a rather restrictive bistream API that doesn’t provide bit-granularity control over what you submit. That’s kind of problematic if you want to do any kind of bandwidth optimization as every bit counts when you do a multiplayer game with lots of players
EDIT: correcting myself - You can actually send an RPC directly to a target player:
NetworkView - public void RPC( string name, NetworkPlayer target, params object[ ] args );
So after doing a bit of research and prototyping, I’ve narrowed down my choices to either going with Unity’s built-in networking or rolling my own high-level networking system on top of the Lidgren networking library. I went through quite a few threads on Unity’s built-in networking, and it seems to have quite a few bugs, quirks and limitations that really make me question if it can be considered for a commercial game. Sure, it’s quite easy to get a multi-player prototype/demo up and running in a couple of lines, but once you start digging a bit deeper you very quickly bump into the limitations of the API and some of the yet-to-be fixed bugs. Improving Unity’s built-in networking doesn’t seem to be high on the dev’s priority lists either.
Has anyone actually released a commercial multiplayer game using Unity’s built-in networking?
I’m not sure what the aim of your project is, but if you want to go commercial with lots of players, I suggest you take another look at the networking solutions and of course Photon.
Compared to Lidgren, they offer you a lot more on the server side. Seemingly easy stuff, like organizing players into rooms, sounds easy but sometimes isn’t. At least not, if you need a solution that scales well with available CPUs on your server. And that’s what a commercial solution will require.
In any case: Let us see how you do. Looking forward to your progress.
I’d love to find someone who allows you to use Unity for the server game logic, but supports a better networking library, whether built on top of lidgren or otherwise. We’re doing a client-server game as well, as the limits I see with Unity:
Network Instantiation is unreliable, so you end up needing to do a really horrible hack between RPCs for spawning objects, and network view synchronization for updates. The networkview synchronizations with this are extremely ugly, requiring stuff like destroying all network views and recreating them whenever a new player connects (otherwise you’ll get errors where the network views never connect since it sent initial data before your client had the object).
No way to limit bandwidth per player. Meaning, I’d like to send less updates, the less important an object is, based on distance or some other metric. Unity’s networking scales horribly right now - everyone sends out full data (reliable compressed etc) if they are in scope.
Some way to visualize where bandwidth is being used, IE what RPCs, what percentage based on which components are synchronizing, etc.
Networking has fairly horrible performance if you scale up to 30-50 networked objects - I assume it’s because we’re using reliable compressed and it’s trying to diff all the data 15 times a seconds. Using a dirty flag system instead would optimize a lot of that if that’s the reason the profiler is indicating high %. But the profiler tells you no info except Network.update().
Use some sort of unreleable ackd packets for network updates instead of having everything go through a reliable UDP system, to allow unimportant data to be dropped/resent if needed instead of backing up the whole payload.
Total bandwidth limit per connection, so that it will send less network view synchs if there’s been too much data sent the last second, and prioritize any RPCs over networkview synchs, and then fill the remaining based on the priorities in #2.
Raknet can support all of this - I’ve used it previous for C++ projects. But it’s not exposed to Unity. And standalone Raknet isn’t usable, AFAIK, if you want to do a web-based multi-platform client.
I’ve looked at Photon and it seems to be missing some of these features. I’m guessing I’ll eventually write this layer if noone else does.