x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

Code-spawned sounds destroyed with no OnAudioFinished

Hi,

I'm spawning sounds in c++ and keeping the pointer to them in order to add effects to them later. I also register an OnAudioFinished callback to destroy the sounds once they're finished and remove their pointer from the list.

At some point in the game, I want to stop and destroy all of the sounds. This usually works with no problem, but very rarely, one of my sound pointers is invalid, while still being non-null, meaning that I never got the OnAudioFinished callback.

I've tried many things to try to work around it, but nothing works. I've made sure I wasn't destroying sounds any other way, the code is pretty straightforward. Has anyone ever had this issue or something similar?

 // Spawn sound with autoDestroy to false
 UAudioComponent* tmp = UGameplayStatics::SpawnSoundAtLocation(this, sound, location, FRotator::ZeroRotator, volume, pitch, 0.0f, nullptr, nullptr, false);
 
 // Register the callback using OnAudioFinishedNative instead of OnAudioFinished because the sound pointer is a parameter of the callback.
 tmp->OnAudioFinishedNative.AddUFunction(this, FNAME_ON_AUDIO_FINISHED);
 m_allSounds.Push(tmp);
 
 ...
 
 void MyClass::OnAudioFinished(UAudioComponent* audioComponent)
 {
         // code to find sound in m_allSounds
 ...
         // Stop and destroy sound.
         // Crashes here on the first access to the pointer.
         sound->OnAudioFinishedNative.RemoveAll(this);
         if (sound->IsPlaying())
             sound->Stop();
         if (!sound->IsBeingDestroyed())
             sound->DestroyComponent();
         m_allSounds.RemoveAt(index);
 }
 
 ...
 
 // Code to destroy all the sounds.
 for (AllSoundsStruct& sound : m_allSounds)
 {
     // Shouldn't happen.
     if (!sound.m_sound)
         continue;
     sound.m_sound->OnAudioFinishedNative.RemoveAll(this);
     if (sound.m_sound->IsPlaying())
         sound.m_sound->Stop();
     if (!sound.m_sound->IsBeingDestroyed())
         sound.m_sound->DestroyComponent();
 }
Product Version: UE 4.18
Tags:
more ▼

asked Jul 13 '19 at 09:40 PM in C++ Programming

avatar image

ItBurn
85 7 7 12

avatar image ItBurn Jul 15 '19 at 04:48 AM

Seriously, I've tried everything. Mutexes, using UObjects and AddDynamic, autoDestroy, and a million ways of doing the same thing differently... Moral of the story is, if I try to stop any sound manually, it'll start causing AudioComponents to start being destroyed/corrupted without notifying me.

avatar image Moe Wattar Jul 15 '19 at 06:40 AM

Can you show me definition of AllSoundsStruct and m_allSounds?

avatar image ItBurn Jul 15 '19 at 06:52 AM

To be clear, the code I posted at the top is more like pseudo code, but you get the idea.

 struct AllSoundsStruct
 {
     UAudioComponent* m_sound;
     float m_initialPitch;
 };
 
 TArray<AllSoundsStruct> m_allSounds;
(comments are locked)
10|2000 characters needed characters left
Viewable by all users

1 answer: sort voted first

Okay, could you try switching your struct to a USTRUCT() and the pointer to the sound to a UPROPERTY() and try again?

more ▼

answered Jul 15 '19 at 06:54 AM

avatar image

Moe Wattar
463 8 5 7

avatar image ItBurn Jul 15 '19 at 06:55 AM

My code is currently a wasteland after the dozens of workarounds I tried to implement and also it can take up to 4 hours to reproduce the issue, so it might take a bit of time but I'll try. I hold very little faith in this though :p

avatar image Moe Wattar Jul 15 '19 at 07:06 AM

I had a similar problem before so i know what it's like to try everything and being frustrated.

Anyway, the only explanation that seemed probable at the time when a UPROPERTY() fixed my problem is as the documentation says, an Object reference stored in a raw pointer will be unknown to the Unreal Engine and will not prevent garbage collection. The pointer gets nulled before the code reaches the OnAudioFinished callback or your custom destruction code.

avatar image ItBurn Jul 15 '19 at 07:12 AM

Sounds promising I'll give you that.

avatar image ItBurn Jul 16 '19 at 03:50 PM

It does seem like my issue, in part, was missing UPROPERTY() tags, probably... I also use the AudioComponents in a non-UObject class and this is preventing me from using UPROPERTY() in this case. So I might have to refactor that. I tried to use AddToRoot() to bypass that, but it turns out that attached sounds are actually not "stopped" when the component they're attached to is destroyed, they're destroyed (even if you set it to NOT autoDestroy), which asserts when RemoveFromRoot() hasn't been called, and there's nothing I can do. I think I'll be able to fix the issue with some code refactoring, unless my time consuming tests prove that it wasn't the issue...

(comments are locked)
10|2000 characters needed characters left
Viewable by all users
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question