Download

Proper way to Destroy an an Attached actor?

I have problems getting to work the detaching of an static mesh for network mode.
I spawn an actor, which is basically a StaticMesh in network mode, gets replicated correctly.

The problem happens when detaching the static mesh. If the involved actors are relevant the system works ok, but if one of the actor becomes irrelevant and return the the area where a detach action happened, an artifact of the static mesh remains in the world.

I am not sure if this is related to the way I am destroying the StaticMesh or I need another network mechanism to handle the situation. But anyways the static mesh was destroyed and there is no reference to keep for it.

I spawn the static mesh with the SpawnActor and attach to mycharacter .



AMyActor* MyActor = Cast<AMyActor>(GetWorld()->SpawnActor(MyStaticMeshClass, &PlayerLoc));

MyActor->MyStaticMesh->AttachTo(MyCharacter->GetMesh(), MySocket, EAttachLocation::SnapToTarget);


Later when I remove this actor,



StaticMesh->Destroy();


I tried calling other methods, previous to the destroy just for testing



DetachFromParent
DestroyComponent
ConditionalBeginDestroy


But all ended up with the same artifact problem.

For the SpawnActor part, I also tried adding FActorSpawnParameters so that the parent of the object is explicit, but I didn’t make any difference.

Perhaps I should Destroy the actor through the Owner???
Please, give me your advice on how to properly destroy it or what the missing piece.

NOTICE: the actor is actually detached and destroyed for the own player and the others. The only problem is for the others, where the static mesh artifact remains in the world.

Thank you.

Seems the attached static mesh has a different relevancy to its parent.
Fix that and it should fix your problem.

Check out bNetUseOwnerRelevancy and GetNetPriority().

You could also try calling ForceNetUpdate() immediately after the actor is detached/destroyed.

Thanks for pointing me to the right direction Kris.
I have experimented a bit with the flag, indeed there seems to be a problem with it.

I tried changing the bNetUseOwnerRelevancy from the default constructor and also with SpawnParams, but I never got the appropriate GetNetPriority calls. This property it’s probably been override somewhere.

In ActorReplication, I was expecting these lines to be executed



	if ( bNetUseOwnerRelevancy && Owner)
	{
		return Owner->GetNetPriority(ViewPos, ViewDir, Viewer, InChannel, Time, bLowBandwidth);
	}


Maybe my SpawnParams are still wrong.

I noticed that the actor I use to spawn contains a MeshComponent, but I can’t really change the MeshComponent bNetUseOwnerRelevancy. Maybe I need to create my own version of a MeshComponent??

The only way I have managed to call those lines in ActorReplication, is setting the bRemoteOwned to true, but this will be checked in PostNetInit as an error. I guess the remote role should be change to ROLE_SimulatedProxy, but it will be tested against authority, any advice about changing the RemoteRole?

Provided bReplicates is true, the remote role should already be set correctly.
Check out AActor::PostInitProperties() & AActor::SetReplicates(bool bInReplicates).

Is this static mesh solely created and destroyed on the server?

No, a multicast function is used to replicate the object to all clients upon creation and destroy.

It seems to be a very specific problem related to static meshes, I tried testing it using skeletal meshes it works correct.
And yes, SetReplicates & PostInitProperties are correctly setup.
Still can’t hit the breakpoint line in ActorReplication::GetNetPriority.

What about those flags in PostInitPorperties??



	// Under some circumstances sub-object instancing can result in bogus/duplicate entries.
	// This is not necessary for CDOs
	if (!HasAnyFlags(RF_ClassDefaultObject))
....


Maybe an extra flag is missing in my object. Could this be related?

Another question. For AActor::ResetOwnedComponents(), I should expect the StaticMeshComponent to be replicated as well, right?
It is always set to false, no matter if I change the Owner and SetReplicates(true).

Last thing, as you might notice in my first post, the static mesh is a component of an actor I called MyActor.
In the default contructor of MyActor, I create the static mesh component



MyStatMeshComp = ObjectInitializer.CreateDefaultSubobject<UStaticMeshComponent>(this, TEXT("StaticMeshComponent"));


I am not sure what’s the replication behavior of this.
The MyActor is already setting replicate to true, are the components of this actor affected by it or not?

I found my bug, and as I mentioned it was related to static mesh only.
Whenever MyChar was getting out of relevancy it was destroyed using the base Pawn:: Destroyed. Overriding the function and cleaning up all relevant components (i.e. static meshes) everything works fine.

So, if you guys get this problem again, make sure your relevancy stuff and everything is set up correctly, but ALSO make sure your pawn is destroying all its attached components.
Thank you.

Ahh, I should have asked that to begin with.
Or did I simple misread?

In any case, yeah, that changes things.
Its essentially like you’ve create two different statics meshes - one server, one client.
You would need to manually tell the client side version to be detached and destroyed.

You’re right Kris about the two different version, the system was already destroying the client versions, but still artifacts were generated.

Just to stress that this problem was related to the pawn and its components: how the Pawn was Destroyed when coming out of the relevancy.
Event though the static meshes were components attached to the Pawn, whose owner was the Pawn, the base Pawn:: Destroyed wasn’t capable of cleaning up all the components (perhaps another Pawn flag or an engine restriction), reason I override it and made sure all the static mesh components were destroyed.