how to play sound by file name

is it possible to play(or get the reference of) a sound by it’s path/filename?

more info: i have around 300 sound files each with a specific name that are all stored inside an array of strings, i need to take a string from the array and play the sound with that name, i come from unity where you can just do


AudioClip clip = Resources.Load(stringVariable);

That is not really the Unreal engine way to do it. I mean you can find the object using the string, sure, but tbh you would be better storing the actual object. But as it is a very big list, what you would want to do is


 
 USoundBase* Sound = LoadObject<USoundBase*>(NULL, StringVariable, NULL, LOAD_None, NULL); 

or something similar.

You can make that a bit better.


    template <typename ObjClass>
    static FORCEINLINE ObjClass * LoadObjFromPath(const FName &Path)
    {
        if (Path == NAME_None) return NULL;
        if (Path.ToString().Contains("None")) return NULL;
        return Cast<ObjClass>(StaticLoadObject(ObjClass::StaticClass(), NULL, *Path.ToString()));
    }


FString Path = FString::Printf(TEXT("/Game/PoppyAndBuddy/Stories/%s/Audio/%s/%s"), *BookName, *Language, *Word);
USoundWave* Loaded = LoadObjFromPath<USoundWave>(FName(*Path));

e.g. an actual, exact example path is /Game/PoppyAndBuddy/Stories/MyStory/Audio/English/hello

So not a typical asset reference, it’s just straight up a normal path using /Game as the root.

2 Likes

You can also use ConstructorHelpers:FObjectFinder<> to snag a sound from a file path. The only thing to note based on your post descriptions is you currently have an array of strings with each path name, and you would need to use TCHAR* or wchar_t ] to store your paths. Here is some code to grab a single sound by path using two acceptable types:

in your .h


UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Ammo)
class USoundBase* AmmoPickupSound;

in your .cpp’s constructor


TCHAR* SoundPath = L"SoundCue'/Game/SciFiWeapLight/Sound/GrenadeLauncher/GL_AmmoPickup_Cue.GL_AmmoPickup_Cue'";
auto AmmoPickupSoundAsset = ConstructorHelpers::FObjectFinder<USoundBase>(SoundPath);
if (AmmoPickupSoundAsset.Object != nullptr)
{
    AmmoPickupSound = AmmoPickupSoundAsset.Object;
}

or


wchar_t SoundPath] = L"SoundCue'/Game/SciFiWeapLight/Sound/GrenadeLauncher/GL_AmmoPickup_Cue.GL_AmmoPickup_Cue'";
auto AmmoPickupSoundAsset = ConstructorHelpers::FObjectFinder<USoundBase>(SoundPath);
if (AmmoPickupSoundAsset.Object != nullptr)
{
    AmmoPickupSound = AmmoPickupSoundAsset.Object;
}

Then when you want to play a sound somewhere you can use something like:


if (AmmoPickupSound != nullptr)
{
    UGameplayStatics::PlaySoundAtLocation(this, AmmoPickupSound, GetActorLocation());
}

Hope this helps, have a lovely day!

Issue with Constructor helper is you need to load them ALL in the constructor. not very memory effecient and you would need an array to hold all the pointers, and then loop through to pick the sound you want.

2 Likes

The method I posted works outside of the constructor, so it has that going for it which is nice.

We have a similar requirement in one of our projects.

  • thousands of lines of recorded dialog
  • each dialog line is referenced by a unique string which maps to a sound cue asset
  • a TMap<FString, FString> associates unique dialog cue name to an asset path

We use the same loading method as Antidamage posted above. Though we just directly play the sound cue through a player controller reference.



 USoundCue* chatSound = Cast<USoundCue>(StaticLoadObject(USoundCue::StaticClass(), NULL, *soundCuePath));
 if (chatSound != nullptr && _playerController != nullptr)
 {
    _playerController->ClientPlaySound(chatSound);
  }


2 Likes