Spatially loaded actors that will refuse to unload when all region are unset in the Editor

Dear Community,

I have a problem on several actors that will not unload when I remove all the regions in the editor. All my datalayers are enabled by default. For the context, I use a World Partition level and One File Per Actor enabled. I checked that these actors are Spatially loaded and they belong to one datalayer (Roads in this case). They are not even pinned. I want to add that when the level is freshly loaded (with no region), the scene is empty.

I was told that having references to other actors can explain my issue too and I had indeed such connections. For the test, I set all these references to nullptr and I just disabled the subsystem dealing with these actors. I still have the problem as you can see on the following snapshots. Please note that some of them unload correctly (of the same actor class).

[Image Removed]

[Image Removed]

To be sure that I cut all the possible connections, I used this function to list the referencers on an actor: FReferencerFinder::GetAllReferencers (and I used the reference viewer too). This is an example I had for an actor having the issue (please consider attached file Referencers.txt)

I’m starting to run out of ideas. Where should I put a breakpoint in the code to know why these actors are not unloaded? What are the reasons why my actors would refuse to unload?

Thanks in advance,

Philippe

Hello,

I was able to point out the culprit by dissecting the actors. There was another subsystem handling the loading and unloading of a given component. This component has a TSoftObjectPtr<Actor>.

So far, no problem, the thing is, when it loads, and because we need to compute a graphe, we needed to force a loading of this TSoftObjectPtr right now, and not wait for the area to be loaded.

There is no particular member storing the reference of this actor, just the fact to call this function, LoadSynchronous on an actor, leads to my problem:

if (!ViewWay.IsValid() && aLoadIfUnavailable && ViewWay.ToSoftObjectPath().IsValid()) { return ViewWay.LoadSynchronous(); } return ViewWay.Get();If LoadSynchronous is not proper way to do, in order to anticipate the loading of an actor, but still being able to clean the region once we delete it, how could I do that?

Thank you,

Philippe

As a follow-up, I replaced the “LoadSynchronous on the actor” approach to have something more like :

`AUnrViewWayActor* FUnrViewWayTrajectory::GetViewWay(UWorld* aLoadIfUnavailable) const
{
const FSoftObjectPath& vViewWaySoftObjectPath = ViewWay.ToSoftObjectPath();
if (!ViewWay.IsValid() && aLoadIfUnavailable && vViewWaySoftObjectPath.IsValid())
{
UWorldPartition* vWorldPartition = aLoadIfUnavailable->GetWorldPartition();
if (const FWorldPartitionActorDescInstance* ActorDesc = vWorldPartition->GetActorDescInstanceByPath(vViewWaySoftObjectPath))
{
FWorldPartitionHandle vWPHandle(ActorDesc->GetContainerInstance(), ActorDesc->GetGuid());
AUnrViewWayActor* vLoadedActor = Cast(vWPHandle.GetActor());
return vLoadedActor;
}
}

return ViewWay.Get();
}`I believe that FWorldPartitionActorDescInstance is more suitable for my case and it seems to work when I want to unload the area, the instances are all released this time. I just hope that it is the right solution.

Philippe

Bonjour Phillipe,

It’s hard to comment on the overall system but it is ok to call LoadSynchronous if you don’t mind that it will block the game thread. Regarding cleaning them, the TSoftObjectPtr does not count as a reference in the eye of the garbage collector so the Actors should go away the next time it executes. This can actually be a problem depending on how the actor is being handled outside the code you shared. TSoftObjectPtr::Get() does return a pointer to the Actor and storing that pointer into a property will result in preventing the GC from destroying it. The opposite is also that the Actor pointer might become invalid with time if the calling code stores it in a non-property member.

Regards,

Martin