Playing Sound in Actor Components..?

I created a base C++ class for interactable items. For each new item a blueprint is created based off the base C++ class, if the new Item needs added functionality a C++ actor component is created to add the new functionality. Right now I am trying to play a sound in the actor component code for a new item(it is a Music Box), I declare a SoundBase in the .h file like this…

UPROPERTY(EditAnywhere, BlueprintReadWrite)
		class USoundBase* Music;

In the .cpp I am trying to play the sound but I don’t know what to put inside PlaySoundAtLocation.

UMusicBoxC::UMusicBoxC()
{
	

	bWantsBeginPlay = true;
	PrimaryComponentTick.bCanEverTick = true;

	UGameplayStatics::PlaySoundAtLocation();
	
}

I read documentation for PlaySoundAtLocation and looked through the GameplayStatics.h file but I can’t seem to get it to work inside the actor component. Does anyone know how to do this? Or have a better way to doing this?

Thanks!!

The problem is that you are trying to play a sound in the actor component’s constructor. You can fix this by calling the function in BeginPlay instead.

You also didn’t put any parameters in the PlaySoundAtLocation function, they are pretty straightforward and as you have looked into GameplayStatics.h then I assume you’ve known what those parameters are, if you are confused of what WorldContextObject are, it can be any UObject instance that overrides the GetWorld function, UActorComponent is one of them, so you can safely use its instance as world context object.

There are basically three sound playback functions in UGameplayStatics: play a 2D sound, play sound at a certain location, and play a sound attached to a scene component. All of them are creating and then manage an audio component in the world, the thing is, it needs a World, and an actor component such as your custom class doesn’t have a valid world during the class constructor.

Like Heapcleaner said, you’re going to want to move the [ UGameplayStatics::PlaySoundAtLocation(); ] into a separate function so that the music plays when you want it to.

Also, PlaySoundAtLocation() requires a sound parameter to be played and a location you want that sound played at. Typically you will take the actor’s (in this case the musicboxC’s) location, and use that so the sound is played ‘from’ the music box.

Thanks Guys you helped a lot! This is the new code…

UGameplayStatics::PlaySoundAtLocation(this, Music, GetOwner()->GetActorLocation());

I just have one last question. Since the SoundBase property is declared in an actor component I can’t Initialize it in the blueprint properties. Is there a way to specify the sound to use in C++ with out using FObjectFinder?

From what I understand, you need to use FObjectFinder because the music file is a part of your game assets. When your game is installed on a different machine, you would need your music files to be included.

I’m not quite sure what you mean by the soundbase initialization though. Could you provide a screenshot?

By Declaring Music with UPROPERTY it exposes Music exposes it to the editor, this allows me to select the asset for Music to use in the editor.

UPROPERTY(EditAnywhere, BlueprintReadWrite)
         class USoundBase* Music;

Here is a screen shot

But since the UPROPERTY is declared in an actor component I cannot pick the asset from the editor. Can you give me an example of using FObjectFinder?

I see. What you will want to do instead is move the music UPROP into the actor class itself and not into an actor component.

if you want the the Music property to be exposed in the actor’s blueprint, just add Instanced keyword in your component. for example:

UCLASS()
class AMyActorClass : public AActor
{
...
UPROPERTY(VisibleAnywhere, Instanced, Category="Audio")
UMusicBoxC* MusicBox;
...
};

This will make the component’s properties (including the Music property) editable in the actor.

Thanks you guys so much! I really appreciate all the help.