[Released] Dissonance: Unity Voice Chat

I found the root cause, we are calling DontDestroyOnLoad for DissonanceSetup game object to make sure it will be transferred to other scenes. Dissonance starts working fine on reconnect when I removed this instruction. So how we should properly configure Dissonance for such multi scenes case?

1 Like

Hi ExyteHQ, I’m on Christmas holiday at the moment. I’ll have a proper look at this in the new year :slight_smile:

From a very quick skim it looks like something isn’t being torn down properly when the disconnection happens, when you reconnect the old state breaks the initialisation of a new audio capture system and everything falls apart from there. The error "Error: Cannot associate preprocessor with Playback filter - one already exists!" indicates that a bit of state (the playback filter) has been setup and was never torn down.

Another thing I spotted is that it also looks like something is causing DissonanceComms.Start to be called after the disconnection (maybe when you reconnect) and I guess this might cause the initialisation to run twice which would cause the same error. Is it possible you have two instances of DissonanceComms at once?

Edit: Sorry, I just saw your second post there. Could don’t destroy on load combined with loading scenes be creating two instances?

1 Like

Just bought the asset and can’t get it to work. What’s the support email?

I just want to use proximity chat but can’t hear anything. The “Tracking” variable of Hlapi Player is always false unlike in the demo, which will be true after connecting to server.

4042360--350980--voice.jpg

1 Like

Hi Dreamer, You can email me for support at martin@placeholder-software.co.uk. I’m on holiday at the moment so I may not reply until the new year :slight_smile:

Tracking being false by itself shouldn’t completely mute voice (it would just disable positional chat until tracking is initialised). There must be something deeper which is breaking voice (e.g. no active broadcast trigger, no active receipt trigger, networking broken somehow). Have a look at the DissonanceComms component, it shows a load of useful information (e.g. what channels you are sending on and what channels you are listening on).

Hi Nyarlathothep, DissonanceComms has information as below:

I didn’t add receipt trigger at all. Because I tested in the demo and deleted all the receipt triggers, room A, room B just to test the proximity chat. And it works just fine without receipt trigger.

I mannualy add 5 components to player objects (both local player and remote players) after they are network spawned:

  1. Hlapi Player, 2. Voice Broadcast Trigger(Set to Self), 3. A shpere collider trigger, 4. trigger visualizer (I can see the circle after player connects), 5. speaker indication (It doesn’t work no matter how close I stand in the circle)

When I speak, I can see mic amplitude value change. But can’t hear and speaker indication doesn’t pop up like in the demo.

I’m new to this plugin. Tried many times and still can’t get it to work.

1 Like

Just in case you’re not sure I’ll clarify exactly how triggers/channels work:

There are two types of channel: Room and Player. If you broadcast voice to a room (e.g. using a broadcast trigger with channel type: room) no one will hear it unless they are listening to that room (e.g. using a receipt trigger). If you broadcast voice directly to a player (e.g. using a broadcast trigger with channel type: player) that player will hear you even if they don’t have a receipt trigger set up.

Using Channel Type: Self is a special case of Channel Type: Player which automatically fills in the player ID for you based on a sibling player tracking script. That explains why you can’t hear anything - the broadcast trigger effectively isn’t doing anything because tracking isn’t initialised and so it doesn’t know what ID to use.

The root cause is that your player does not have Local Player Authority set to True. I just briefly tested this and setting it to False causes the the tracking script gets confused about things (it detected the local player as Remote, and Tracking never became true). If you open an issue on the tracker (https://github.com/Placeholder-Software/Dissonance/issues) I’ll in investigate it properly once I’m back at work :slight_smile:

As a workaround writing your own player tracking script is pretty simple - you just need to implement the IDissonancePlayer interface, return the information it asks for and call comms.TrackPlayerPosition(this) and comms.StopTracking(this) when you want to start/stop tracking a player. The only complex part is syncing the ID across to all of the clients so every client know which ID is represented by which tracker - the current script uses RPC/Command attributes to sync the ID and I guess one of those is being broken by not having the necessary authority.

It’s good know what is the root cause so I have some clues.
Local Player Authority is set to be false for all server authrotative online games. So it’s all controlled by server and difficult to be hacked.
I think it’s a important feature that should be included in this nice plugin. I will open an issue as you mentioned.
Meanwhile, I will look into it. Hopefully, you will come with a fix soon. Thx.

1 Like

@Dreamer_1 I’m back off holiday now so once I’ve cleared my backlog of support emails I’ll be looking at the HlapiPlayer tracker and whether I can make it work without Local Player Authority. Have you had any luck doing it yourself?

@TheDeepVR do you still need help with your issue or did you manage to resolve it?

I moved on other parts of project.
As I’m not familiar with the plugin, it will cost me a lot more time to dig into it and it’s difficult for me. I’m waiting for a fix. And you are waiting for me these days?

1 Like

Hi Dreamer, I actually developed a fix 4 days ago but I forgot to update you. I’m really sorry about that!

I’ve posted a couple of links on your issue tracker issue where you can downloaded the modified files. Just overwrite the files in your project with those to apply the fix. This fix should be included in the next Dissonance release (probably within a couple of weeks).

Still doesn’t work. And it shows No player id or Tracking for other remote players.

1 Like

Hi Dreamer, sorry about that. I went back and had a closer look and spotted something that I’d missed - it worked if you were looking at it from the perspective of a client, but not from the perspective of a mixed client/server! I’ve posted another link in the issue tracker to overwrite the HlapiPlayer.cs with some additional fixes.

It works now if HlapiPlayer and VoiceBroadcast Triggers are predefined on the player prefab. (It didn’t work before your last fix)

But it doesn’t work if these components are added by script in game.
Because not all the players object in game require voice-chat components for my project. For each player object in game that requires voice-chat, these components are added in player’s initialization script after player is network spawned on Server, local client, remote clients.

By adding these components by script in game, voice-chat doesn’t work. And HlapiPlayer now shows type “Unknown”, tracking is false, no player id.

1 Like

The script uses two methods from HLAPI to start itself up:

  • OnStartClient
  • OnStartLocalPlayer

So if you add your script later those methods never get called because the startup events have already happened before the script even exists. I experimented with using isLocalPlayer instead to avoid needing these method calls but that wasn’t very reliable (it looks like isLocalPlayer doesn’t get set straight away). Unfortunately I don’t know of any options for detecting if this is the local/remote player besides using isLocalPlayer property or the OnStartLocalPlayer method.

I would suggest simply calling that methods yourself when the script is added.

Another option would be to have a player tracker attached to every player so it gets initialised automatically and then adding/enabling the VoiceBroadcastTrigger component later.

1 Like

To let OnStartClient, OnStartLocalPlayer work, I now put the AddComponents in Awake. Now it works, thanks to your explanation.

  1. There is still one issue. If UseColliderTrigger is set true, I can’t hear anything. And the “Trigger Visualizer” won’t be highlighted like in demo when I’m in remote player’s circle. I want this to be true, so it won’t send voice over network the whole time but only send when it’s necessary to save resources. (Because it’s 60-100 players per match)

  2. To maxmize the performance of online game, I tend to keep the components on objects as less as possible.
    Can you tell me to make proximity chat work in my topdown shooter game, which is required and which is not required on Client Local Player Object, Client Remote player objects, Dedicated Server?

Hlapi Player (Does server require it?)
Broadcast Trigger
Sphere Collider
Trigger Visualizer (I won’t add it in final game, so don’t worry about this one)
Speaker Indicator (I want to show it in final game, so I know who talks. Server doesn’t require it, right? And how about local player object?)

1 Like
  • HlapiPlayer - required on clients, but not on the server. Server neither sends of receives audio so it doesn’t matter at all.
  • Broadcast Trigger - required on all clients attached to all local copies of remote players.
  • Sphere Collider - Same as Broadcast Trigger.
  • Speaker Indicator - Same as Broadcast Trigger.

Generally everything in Dissonance is done on the client side. So if we look at this from the perspective of a client (Alice) trying to talk to another client (Bob):

Alice walks around the environment, she can see a game object which is her local representation of Bob. When she walks near the Bob gameobject she triggers the Sphere Collider (locally), this checks if the triggering gameobject has a HlapiPlayer component tracking the local player, if it does it activates the Broadcast Trigger (locally) and starts sending her voice to Bob.

Now the other way around. When Bob hears Alice speaking the local Speaker Indicator component attached to the Alice gameobject first looks at the HlapiPlayer object (to discover which remote speaker this object represents) and then looks at the audio passing through the local audio decoding pipeline assigned to that player and pulses the orb as the amplitude varies.

Hopefully that makes it clear why the components need to go where they do :slight_smile:

If UseColliderTrigger is set true…

According to the above info is your trigger setup correct? Is the tracker tracking? If you just log when the trigger is triggered does it happen when you expect? Keep in mind that the trigger only triggers Dissonance broadcast if the triggering object has a HlapiPlayer component tracking the Local player.

  1. After investigation, I found why it’s not triggered. My players’ collision layer set to not to be collided with each other for my gameplay. If I set collision layer to be true, it works. What I can do to make it work and avoid to change gameplay?

  2. When I don’t add HlapiPlayer on server. It will trigger and error on clients and I can’t enter the game. (It won’t happen if I add HlapiPlayer on server)

IndexOutOfRangeException: NetworkReader:ReadByte out of range:NetBuf sz:45 pos:45
UnityEngine.Networking.NetBuffer.ReadByte () (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkBuffer.cs:35)
UnityEngine.Networking.NetworkReader.ReadUInt16 () (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkReader.cs:179)
UnityEngine.Networking.NetworkReader.ReadString () (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkReader.cs:290)
Dissonance.Integrations.UNet_HLAPI.HlapiPlayer.OnDeserialize (UnityEngine.Networking.NetworkReader reader, Boolean initialState)
UnityEngine.Networking.NetworkIdentity.OnUpdateVars (UnityEngine.Networking.NetworkReader reader, Boolean initialState) (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkIdentity.cs:751)
UnityEngine.Networking.ClientScene.ApplySpawnPayload (UnityEngine.Networking.NetworkIdentity uv, Vector3 position, System.Byte[ ] payload, NetworkInstanceId netId, UnityEngine.GameObject newGameObject) (at C:/buildslave/unity/build/Extensions/Networking/Runtime/ClientScene.cs:491)
UnityEngine.Networking.ClientScene.OnObjectSpawn (UnityEngine.Networking.NetworkMessage netMsg) (at C:/buildslave/unity/build/Extensions/Networking/Runtime/ClientScene.cs:552)
UnityEngine.Networking.NetworkConnection.HandleReader (UnityEngine.Networking.NetworkReader reader, Int32 receivedSize, Int32 channelId) (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkConnection.cs:469)
UnityEngine.Networking.NetworkConnection.HandleBytes (System.Byte[ ] buffer, Int32 receivedSize, Int32 channelId) (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkConnection.cs:425)
UnityEngine.Networking.NetworkConnection.TransportReceive (System.Byte[ ] bytes, Int32 numBytes, Int32 channelId) (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkConnection.cs:576)
UnityEngine.Networking.NetworkClient.Update () (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkClient.cs:753)
UnityEngine.Networking.NetworkClient.UpdateClients () (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkClient.cs:965)
UnityEngine.Networking.NetworkIdentity.UNetStaticUpdate () (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkIdentity.cs:1092)

1 Like

Sorry, looks like I was mistaken about not needing HlapiPlayer on the server. Dissonance itself doesn’t need it on the server (the Dissonance server is pretty much just a packet relay, it doesn’t need to know player identities). However the HLAPI system needs it on the game object so that it can relay the commands/RPCs used to setup the HlapiPlayer component across the various clients.

Can you separate out the VoiceBroadcastTrigger and collider trigger into a child gameObject and then put that on a different layer?

You’ll need to make sure that the gameObject with the HlapiPlayer component can collide with the collider trigger. The VoiceBroadcastTrigger will ignore all collisions which do not involve a HlapiPlayer component.

Self broadcast will no longer work, since the VoiceBroadcastTrigger is not a sibling of the HlapiPlayer component. Instead you’ll have to write a script to copy the ID from HlapiPlayer.PlayerId component to the VoiceBroadcastTrigger.PlayerId property and use ChannelType Player. Alternatively you should be able to replace this code (VoiceBroadcastTrigger Line 275):

_self = GetComponent<IDissonancePlayer>();

with:

_self = GetComponentInParent<IDissonancePlayer>();

But I haven’t tested that yet.

I create a prefab that contains VoiceBroadcastTrigger, Collider, Indicator, Visualizer. I Instantiate prefab and set it’s parent to player object on Start().

And I have tried both methods:

  1. VoiceBroadcastTrigger Set to Player. Copy player name to VoiceBroadcastTrigger.PlayerId.
  2. VoiceBroadcastTrigger Set To Self. And use _self = GetComponentInParent();

The first method doesn’t work. I can’t hear any thing. Even when UseTrigger on VoiceBroadcastTrigger is off.

The second method works for me. Hope you can make this temp solution to an option for plugin. So that when everytime I update to the latest version, the script won’t be over written.

I’ve already merged it into the plugin so it will work this way in all future versions :slight_smile: