Hi, we are trying to use the new UVoipTalker (available since UE 4.19) in order to have users’ voices spatialized.
We’ve already modified some previous versions of the engine (until 4.18.3) to have the correct association between player id and player voice’s AudioComponent. Our modifications are not appliable anymore with UE 4.19, because of some modifications on FRemoteTalkerDataImpl.
So, we are trying to use the new native way to spatialize users’ voices.
The API seems to be simple, but what we obtain is simply non-spatialized voices.
Having the player character, we do the following things in its Event BeginPlay:
We do the following for each player character spawned on each machine (client or server): we create the UVoipTalker and assign it the VoiceSettings (with the component to which to attach the voice and the attenuation settings). We already use the same attenuation settings before, by attaching them to the same Avatar Head, and it worked perfectly.
Sorry I’m not able to see your image here for some reason- looks like it might be a broken link?
I will say that a common issue with this is that, due to initialization steps, calling **Register with Player State **on BeginPlay will probably be called before you can actually register anything to the Player State. I’ve usually assuaged this with a short delay:
Also, while you’re checking out the UVOIPTalker stuff, I should also mention that you can create a blueprint child class of UVOIPTalker, and in doing so get events for when the registered talker starts and stops speaking:
For example, here I’m just playing a sound when someone starts and stops talking to create a sort of “walkie talkie” effect. If the person speaking is on Windows, this will also take silence detection into account, so you will get Begin Talking events when someone actually starts speaking and End Talking events when they stop, even if you’re not using push to talk or if someone is keeping their push to talk button held down.
Let me know what kind of rad stuff you use the VOIPTalker for!
How do I add/create this voip talker in the right way? With this setup it worked for me once but now it just crashes everytime I try to speak. The “normal” voip setup just works fine and I tested it on the packaged build and in the editor.
I will provide a screenshot of my setup which is almost the same as shown by Ethan.
Has anyone figured out the “right” way to set this up yet?
When APlayerState replicates, the possessed pawn may not have replicated over yet, or the PlayerState property on the pawn indicating possession may not have replicated over yet so you can’t handle it there.
When the Pawn replicates over, the pawn’s PlayerState property may not have replicated over yet so you can’t completely handle it there.
When the Pawn’s PlayerState variable replicates over, the UniqueID on the APlayerState may not have replicated over yet so you can’t completely handle it there.
Once the UniqueID replicates over, you can’t easily handle it because there seems to be no way to get the Pawn at that point (in the OnRep_UniqueId handler) unless you iterate through every Pawn in the game and check if it has a PlayerState pointing to the current one (slow), and the Pawn itself or the Pawns’s PlayerState variable may not have replicated over yet anyway.
Only if you attempt handle it in almost all of those places can it work, but I haven’t figured out how to get the PlayerState’s Pawn in the OnRep_UniqueID without iterating through all Pawns, which may be slow and cause a hitch?
(Edit: the .2 second delay in the official solution above does not look like good practice. I see solutions like that that given in lots of official tutorials on different network things, but it is just wishing away the problem. You don’t see that kind of thing in ShooterGame code, etc.
You need to way until player state, player state’s UniqueId property, the player state’s possessed Pawn property, and the possessed pawn’s PlayerState PlayerState have all been replicated. They can all happen in many different orders, but you can’t fully set things up until they are all there. Maybe that all happens .2 seconds after begin play, but maybe your machine gets choppy and it doesn’t.)
Hi @Ethan.Geller , the solution you suggested works well, only I really don’t love [FONT=courier new]Delays because I’ve seen sometimes [FONT=courier new]PlayerState is replicated after 0.2 seconds, sometimes at 0.4 it has not been replicated yet. At the moment I opted for a continuous polling on the validity of [FONT=courier new]PlayerState with a delay of 0.1 seconds between each check; it is not an optimal solution but is a little more deterministic (sooner or later [FONT=courier new]PlayerState will be valid).
Now, solved that one, we have another related problem…
Do you know why the native spatialization does not work at all with the Oculus subsystem? When we set to use the Oculus subsystem in the DefaultEngine.ini, neither spatialization/attenuation nor the events EventBeginTalking and EventEndTalking work anymore.
@anonymous_user_80eda73a@muchcharles
I agree that the delay is bad practice. I agree with Masmil1988’s idea of using an IsValid check on tick or a delay loop as a more robust way of handling this.
@anonymous_user_80eda73a@Zenteran@A7E7
re: different online subsystems: UVoipTalker is only supported with Unreal’s native VOIP support, which is used in the Null and the MCP subsystems.
Is there plans soon, to support sub systems with this out of the box? Most users like myself will be using Steam or something else because this is kind of only useful in multiplayer games.
I don’t understand how you make it work?
On my side, using OnlineSubsystemNull as required, I keep failing with this errors in log:
LogVoiceEngine: Error: StartLocalVoiceProcessing(): Device is currently owned by another user
LogVoiceEngine: Warning: ReadLocalVoiceData: GetVoice failure: VoiceResult: Ok
LogVoiceEngine: Warning: Voice data error in ReadLocalVoiceData
My DefaultEngine.ini (the section related to voice):
Edit: @Ethan.Geller I managed to don’t have the “Error: StartLocalVoiceProcessing(): Device is currently owned by another user” error anymore by modifying **FOnlineVoiceImpl::RegisterLocalTalker(…) **(VoiceInterfaceImpl.cpp:185) and placing the call to Return = VoiceEngine->RegisterLocalTalker(LocalUserEnum) before the call to **StartNetworkedVoice(LocalUserEnum). **But it still does not work in the end…
I was able to do it by having VoiceInterfaceSteam use FVoiceEngineImpl instead of it’s own voice engine; the only other main change was using unique net ids converted to strings instead of directly for mapping the talkers (the ids are an opaque type).
I am also having issues with VOIPTalker. I feel like my subsystem is not correct. This is how I register my VOIPTalker as Ethan.Geller posted. I’ve confirmed that the code is run ( the player state is around eventually… and the VOIP gets “registered”).
//DefaultGame.ini has
[/Script/Engine.GameSession]
bRequiresPushToTalk=false
I am building my engine from source (I don’t think this matters), and I’m trying to use the Null subsystem. Maybe I’ve missed something obvious (does this work in the PIE editor window? do I have to use a different subsystem? maybe I can’t use a sourcebuilt engine?