Closed PedrelliLuca closed 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()
.
If you cast the "IceShard" spell, when the shard gets destroyed you'll assert with the following call stack:
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, likeBeginDestroy()
. I was having problems with this latter though, since it gets called during the engine boot...