Particle system material garbage collected

Hello,

There has been a very annoying bug in the packaged version of my game where it would occasionally crash due to random particle system component related code. Today I luckily ran into the crash while debugging (DebugGame config) and got a helpful crash log. The output informed me that a material of a particle system required module was invalid.

So I figured the reason for this must be that the material is garbage collected for some reason. I am dynamically loading the particle system during the game with this code:

 // Some code
 static UParticleSystem * ExplosionEmitter = UBrickGameInstance::SynchronousLoad<UParticleSystem>("ParticleSystem'/Game/BrickRigs/ParticleFX/Fire/P_Explosion.P_Explosion'");

Loading function:

 template<>
        inline UParticleSystem * UBrickGameInstance::SynchronousLoad(const FString & AssetPath)
        {
            // Inside the loading function
            UParticleSystem * ParticleSystem = LoadObject<UParticleSystem>(NULL, *AssetPath);
            	if (ParticleSystem)
            	{
            		ParticleSystem->AddToRoot();
            }
    
    return ParticleSystem;
    }

So I added this code as a workaround and it seems to have fixed the issue:

for (UParticleEmitter * Emitter : ParticleSystem->Emitters)
		{
			for (UParticleLODLevel * LODLevel : Emitter->LODLevels)
			{
				if (LODLevel->RequiredModule->Material)
				{
					LODLevel->RequiredModule->Material->AddToRoot();
				}
			}
		}

Although the workaround seems to be working, it’s not a nice solution so I would be glad to hear the reason why it didn’t not work in the first place. Am I missing something? Shouldn’t it be enough to add the particle system to the root?

Hey Fluppi,

Could it be that it gets collected as garbage because your particle system does not have an outer when it gets created? LoadObject(NULL, *AssetPath);

Maybe if you put the outer to the right UWorld it will not get collected as garbage. I also ran into similar problems like this and was able to solve it this way.

Hope this helps :slight_smile:
Elias

Thanks for the response. Maybe it would prevent the material from being garbage collected if the particle system had an outer object, but that doesn’t really work in my code since all my LoadObject calls are static, i.e. I cannot use the world or an actor or component as outer since they could be deleted until the next time the particle system is needed. AddToRoot is supposed to prevent any object from being garbage collected, which also works in all other cases.
I based my code on ConstructorHelpers::FObjectFinder, which uses these exact lines:

T* ObjectPtr = LoadObject<T>(NULL, *PathName);
		if (ObjectPtr)
		{
			ObjectPtr->AddToRoot();
		}

Ah ok I see,
have you tried setting the particle system and materials as UPROPERTY’s? I actually just had also a problem where something got deleted and by setting the array to uproperty it stopped happening. Not sure if it will help you :slight_smile:

Yes very likely that would also prevent the crash, at least I never experienced an object being garbage collected from a UPROPERTY. However in some cases this is not really a nice solution, for example when I want to spawn a generic explosion from a static function where I don’t have a place to store UPROPERTY’s.

I guess the question is not really about finding a workaround, since I already have one for this specific case. I would rather like to know why this happened in the first place, and if it is a bug or meant to be like this?