• Register

Is a highly asymmetrical multiplayer game where winning means bribing and coercing opponents into helping you win.

Post news Report RSS OBEY gains in-game voice chat

What you can learn from my battle to implement player voice chat in Unity.

Posted by on

Wow! I just submitted the first version of OBEY with in-game voice chat for publishing!


A huge step has been accomplished in getting the game ready for release on Steam.

OBEY is a Unity game.
If you enjoy technical posts, let me tell you a story about what it is like to implement in-game voice chat in Unity.

Step 1) Don't reinvent the wheel.

I started by buying a license to use Daikon Forge's DF Voice plugin. It converts the microphone data into something you can manage and pass around in the game. It doesn't care how you pass it or where you send it to, that's for the dev to take care of(as expected).

Step 2) Design an Architecture.

Considering that if players want badly enough to communicate with each other against the spirit of the game (ie cheat by spectating and informing another player) it would be so easy to sidestep any security measure in the game that it would not be worth having security at all. Secondly, since voice data is also not the most vital data in a game, if some packets are lost it is not a big problem and players can repeat themselves regardless. Therefore I decided that the best way to send voice chat would be to stream it unreliably peer-to-peer among players, and avoid taxing the server at all with voice functionality. This seemed a pretty obvious approach since I couldn't think of a good reason to not stream or to expend server resources on voice chat.

Step 3) Implement it.

DFvoice comes with some examples using RPC calls to get voice packets from one computer to another. RPC's are verified and would waste bandwidth confirming and re-sending lost packets. So I started building a system that would stream the voice data (not use RPCs). DFVoice gives the voice data as byte[] arrays. Unity's bitstream.serialize() method does not accept byte[] so that meant I would have to send it in another format, and then convert it back.
I wrote a method that would buffer, split it up, and serialize it bit by bit as bools, and another that buffers those and reassembles them. I thought I had crashed Unity when I first ran it. But I hadn't. It was just so slow that it would not even be worth trying to optimize it to get it to work. After trying a few other things, I realized that there was no way to get it from one machine to another using any form of unreliable streaming because either the method would be too nasty a hack and/or be unreasonably slow because the Unity bit stream class does not accept any form of... well... bit streams. Sigh. I could sidestep it by integrating yet another library... or god forbid, torture myself with sockets .
Instead I rewrote the system again, this time biting the bullet and using RPC's peer-to-peer. It wouldn't be as fast as it could be, but the voices would be reliable and very clear. After spending the time I could not get it to work. I also could not find bugs, my code was good. What was going on? Well it turns out Unity has nuked the concept of peer-to-peer (even though it uses Raknet under the hood, which is fundamentally peer-to-peer networking library). You can't do ANYTHING peer-to-peer via Unity's native networking paradigm. I would have to send the data via the server.
So again I bit the bullet... this time really hard, rewriting the entire system YET AGAIN, to utilize RPCs and send them to the server and then via RPCs again to appropriate clients.
This worked.
But only after trying every logical and (imo) best practice way failed.
I had to architect it in the EXACT OPPOSITE way that I had wanted, for it to work.
I haven't yet encountered enough problems with it to push me to rewrite it again using another library, but this is word to the wise:

If you ever want to add voice chat to your Unity game, prepare to do it in one of 3 ways:
1) using very nasty hacks
2) using a 3rd party networking library
3) modify Unity itself
4) the most ass-backward way from an architecture perspective

I hope this helps someone.

PS
I don't regret using Unity's native networking system. It does what it is supposed to do, and I know it is built around making things 'user friendly', I just wish that I had known what I know now before starting.

Post a comment

Your comment will be anonymous unless you join the community. Or sign in with your social account: