Placeholder-Software / Dissonance

Unity Voice Chat Asset
71 stars 5 forks source link

[help] After pause I hear all the things that I'm missing in Global room #87

Closed juzpermsky closed 6 years ago

juzpermsky commented 6 years ago

Hello.

I started with HLAPI integration on demo scene, where I have a single empty object with the following components: image image I've tried multiplayer with local Host in Editor's Play Mode and Client on Android mobile device, connected via Wi-Fi. It was all fine until some player paused. After getting back to the game player hear all the things that were missed in the Global room It seems like voice data is sent over TCP rather than UDP, even as unreliable channel is used.

But it's not what I was expecting. Is it normal behavior? Can I fix it?

Thank you.

martindevans commented 6 years ago

How is your pause implemented?

In editor Dissonance should handle pausing (using the editor pause button) by stopping sending/receiving voice when it is paused, and then resuming sending/receiving when resumed. You probably need to implement something similar for your game - when paused find all of the VoiceBroadcastTriggers and VoiceReceiptTriggers and disable them. When resumed, re-enable all the triggers.

juzpermsky commented 6 years ago

The problem is not in pause itself. The pause/unpause just reveals the problem. I spent some time for debugging and found out, that in (1client<->1host) simple case described above, the Client sends voice data over UDP as expected, but after receiving the Server relays it over TCP.

I think the reason is in BaseClient.SendUnreliableP2P(...). image It calls writer.WriteRelay wiith last parameter reliable=true. That's why Server relays it over TCP after receiving. Look at stack trace: image

Is it a bug? Or there was a reason to write relay-packet in reliable mode?

martindevans commented 6 years ago

You're absolutely right, that should definitely not be sending with reliable=true! Well spotted.

Does changing that to false fix your problem with hearing too much audio after a pause?

juzpermsky commented 6 years ago

I fixed that, but the problem persists. After being on pause within 10-20 seconds I hear all that was missed. Although, I suppose now that it is normally expected behavior :) Perhaps it's because even being on pause, player's socket continues to receive the data. Default UDP socket receive buffer size (on Android device and on Ubuntu 16.04 in my case) is big enough to accumulate received voice data. And after unpause, the application receives the whole batch. So, I heed your first notice. To fix that, I think I should turn off broadcasting to paused players, on all active players. Maybe, on suspending, the player must notify the remaining broadcasters about it via some kind of ClientState message, to stop them broadcasting to him. Or he should say: "Guys! I'm leaving THIS room for a while! Don't Spam me yet". Or after unpause, he should somehow detect the old batched voice data received from socket's buffer, and just drop it to dev/null.

juzpermsky commented 6 years ago

I re-read your first comment. Did you claim that disabling my own Broadcast/ReceiveTrigger, when I'm going on pause, will generate the one network notification for all and they will stop broadcasting to me? And I suppose that disabling ReceiveTrigger is a lot more meaningful.

juzpermsky commented 6 years ago

Oh! I See! VoiceReceiptTrigger.OnDisable() generates "DeltaChannelState" network message in the end.

martindevans commented 6 years ago

It looks like you've worked it out, but just in case:

However your pause works it is presumably pausing audio playback - the client receives the data and it just buffers up somewhere rather than immediately playing through the speaker. Dissonance does have some handling for desyncs (i.e. your clock and my clock are not running at the same speed) but it will not handle someone beginning to talk while paused (because no audio playback is happening, and the desync compensation happens as part of the playback pipeline).

VoiceBroadcastTrigger controls which rooms/players you are sending to. VoiceReceiptTrigger controls which rooms you are listening to. If you disable all of the receipt triggers you will no longer be listening to any rooms, and so you won't have this problem with audio buffering up (as you say, it sends a DeltaChannelState which causes the server to remove this client from the set of listeners).

There are two potential problems with this solution:

1) It's possible for a VoiceBroadcastTrigger to send directly to a player. In this case the player doesn't not require a receipt trigger and will receive the transmitted voice. If you don't use direct to player speech this isn't a problem. 2) The message to stop listening may take some time to arrive, if you pause immediately upon sending it there will still be a small amount of speech buffered up. If the desync compensation is working correctly Dissonance will discard most of it, only new transmissions which start during this window will be a problem.

If those things aren't a concern, that's great! If they are then there are still some possible solutions (depending on how your pause is implemented):

martindevans commented 6 years ago

Dissonance 6.2.0 has just been submitted to the asset store, this includes the (un)reliable relay fix. This should be available in a few days once the asset store team reviews it :)

martindevans commented 6 years ago

Dissonance 6.2.0 is now available on the asset store so I'll close this issue now. Don't hesitate to re-open it if there's still a problem :)