Download

Audio Ears on the Character, not the Camera?

We are working on a third person shooter project and the camera is a few feet behind the character so he is well in view. When dialing in audio attenuation I noticed that the “ears” of the player are on the camera and not the character in front of you, so attenuated sounds can be noticeably louder when facing away from them. I get it, makes sense as a spectator with a camera, but not great for spatial awareness while imagining you are the Character - not watching twelve feet behind him.

I researched/googled all sorts of docs/links and found nothing on changing this default setup. Is there a way to put the “ears” of the player on the character/capsule, not the camera?

Sorry if a simple question, I am a seasoned animator but a total newb in UE4 programming. Any info or a doc you can point me to would be awesome.

Thanks in advance,
Cris

Much digging, different search terms, finally found it.

Set Audio Listener Override

Looking at how to connect it in the PlayerController now.

I made a tutorial about it. I hope it’s gonna be usefull.
https://www.youtube.com/watch?v=KBzHTX-9BvE

Thanks! Nice tutorial. I was using the first simple method and rotating it 90 degrees in the override node to face it the correct direction, but this looks like fixes other things as well.

My only real issue now is that it is multiplayer, and I’m not sure how to replicate it for all clients without causing other problems. As is, everyone hears the “ears” of the last player that spawns. Another player joins or respawns, now everyone hears those new ears.
Something on BeginPlay needs to iterate only to the new spawned player and not override all existing Server and client players audio.

There is a much easier and more organic way to achieve this without doing anything on tick or hacking together rotations, for future googlers (I know, its an old thread). Override APlayerController::GetAudioListenerPosition() and add:


if (GetPawn())
{
    ViewLocation = GetPawn()->GetActorLocation();
}

In the else statement under GetPlayerViewPoint(ViewLocation, ViewRotation), here’s the full function. The result is that it uses the pawn’s location but the camera’s rotation.


FVector ViewLocation;
FRotator ViewRotation;

if (bOverrideAudioListener)
{
    USceneComponent* ListenerComponent = AudioListenerComponent.Get();
    if (ListenerComponent != nullptr)
    {
        ViewRotation = ListenerComponent->GetComponentRotation() + AudioListenerRotationOverride;
        ViewLocation = ListenerComponent->GetComponentLocation() + ViewRotation.RotateVector(AudioListenerLocationOverride);
    }
    else
    {
        ViewLocation = AudioListenerLocationOverride;
        ViewRotation = AudioListenerRotationOverride;
    }
}
else
{
    GetPlayerViewPoint(ViewLocation, ViewRotation);
    if (GetPawn())
    {
        ViewLocation = GetPawn()->GetActorLocation();
    }
}

const FRotationTranslationMatrix ViewRotationMatrix(ViewRotation, ViewLocation);

OutLocation = ViewLocation;
OutFrontDir = ViewRotationMatrix.GetUnitAxis(EAxis::X);
OutRightDir = ViewRotationMatrix.GetUnitAxis(EAxis::Y);

This worked great! Just a note to inlclude the entire signature when overriding: YourPlayerController::GetAudioListenerPosition(FVector& OutLocation, FVector& OutFrontDir, FVector& OutRightDir)

Nice! It worked so well!
Guys, don’t forget to create your own APlayerController CPP and put

-In the .h file:
virtual void GetAudioListenerPosition(FVector& OutLocation, FVector& OutFrontDir, FVector& OutRightDir) const override;
-In the .cpp file:
void ABasePlayerController::GetAudioListenerPosition(FVector& OutLocation, FVector& OutFrontDir, FVector& OutRightDir) const
{
Super::GetAudioListenerPosition(OutLocation, OutFrontDir, OutRightDir);
Copy and paste the entire code form @Vaei 's post
}

In the GameMode BP set your custom PlayerController CPP as default Player Controller (In my case ABasePlayerController), and you are good to go!

In 4.24.3 the declarations have to be without the const, so

in the .h:

virtual void GetAudioListenerPosition(FVector& OutLocation, FVector& OutFrontDir, FVector& OutRightDir);

and in the cpp:

void APlaneshiftPlayerControllerBase::GetAudioListenerPosition(FVector& OutLocation, FVector& OutFrontDir, FVector& OutRightDir)

The line:

Super::GetAudioListenerPosition(OutLocation, OutFrontDir, OutRightDir);

to me its unecessary as it will just execute the same code in the super class APlayerController. I removed it and it works anyway.

Hi @Vaei !

Could you or some other user “translate” this code in Blueprint? Screenshots or a simple schematic explanation is OK.

I don’t want to use the tick event for this, so your solution should be better but my knowledge of C++ is limited.

It’s C++ only. Also now in GetAudioListenerPosition instead of GetPlayerViewPoint