PedrelliLuca / ScalarField

A TopDown RPG Game, where magic works by interacting with the environment.
4 stars 0 forks source link

Thermodynamics with multiple spherical collisions #96

Closed PedrelliLuca closed 6 months ago

PedrelliLuca commented 6 months ago

If you cast the "IceShard" spell, when the shard gets destroyed you'll assert with the following call stack:

image

The actor being destroyed is the shard. The target character stops overlapping with it and tries looking for the shard's collection on the UCollisionsCollectionSubsystem, without finding it.

I think the shard's EndPlay() has already been called, which results in the shard asking the module to delete its data. I should probably use some function later down the stream of the actor's lifecycle, like BeginDestroy(). I was having problems with this latter though, since it gets called during the engine boot...

PedrelliLuca commented 6 months ago

How did I fix the bug? Here is the call stack explained:

At actor destruction... UWorld::DestroyActor()

we first call... AActor::Destroyed() => AActor::RouteEndPlay() => AActor::EndPlay()

This latter, for each component, calls UActorComponent::EndPlay()

Then flow goes back to UWorld::DestroyActor(), which calls... AActor::ClearComponentOverlaps()

This latter, for each overlap of each UPrimitiveComponent, calls... UPrimitiveComponent::EndComponentOverlap()

this latter function broadcasts two times: one for (this, otherComp), and one for (otherComp, this), so both components are warned about the overlap ending.

After all of this, the flow goes back to UWorld, calling UWorld::RemoveActor()

on the next Garbage Collection, the actor and all its components will be destroyed.

This means all other UCollectionComponents will forget the dying one before its BeginDestroy() => the fix is to utilize BeginDestroy() instead of EndPlay().