Destroying an Actor Referenced in an Array

Hello everyone

I have an array of actors which i use for some purposes through out entire level. When I try to destroy an actor and remove it from the array, i get a crash saying Assertion Failed: IsInGameThread().

Here is the crash log:
Crash Log

This is where debugging leads me to. If i just remove the line that says this->Destroy() everything becomes fine! I am not sure about what i am doing wrong. I hope someone can help me. Thanks in advance.

for(int32_t i = PiecesOnBoard.Num()-1; i >= 0; i--)
{
	AChessPiece * ChessPiece = dynamic_cast<AChessPiece*>(this->PiecesOnBoard[i]);
	if(ChessPiece && ChessPiece->GetPiecePosCurrent() == Position)
	{
		ChessPiece->PieceGotEaten();
		this->PiecesOnBoard.RemoveAtSwap(i);
		break;
	}
}

Here is PieceGotEaten function:

void AChessPiece::PieceGotEaten_Implementation()
{
	CurrentPiecePosition = EPiecePosition::NotOnBoard;
	this->SetActorEnableCollision(false);
	PieceMesh->SetVisibility(false);
	Capsule->SetCollisionEnabled(ECollisionEnabled::NoCollision);
	Capsule->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);

	this->Destroy();
}

try destroying the item after removing it from the array.

It doesn’t make any sense, but still tried and well, crash…

destroy is done at the end of tick, i thought maybe a null pointer might be crashing your game. you can check if your actor is really getting destroyed, Destroy command returns a bool, if true your actor is/will be destroyed. you can also try K2_DestroyActor instead of Destroy. Another thing, you can call garbage collection right after destroying: GetWorld()->ForceGarbageCollection(true);… also before calling you class method, why not check if it is valid? if(!ChessPiece) continue; and if(!ChessPiece->IsValidLowLevel()) continue; maybe…

I spent some time on playing around. But it seems the cause of the problem is elsewhere while the problem occurs there. I will try to play around a bit more and find out what is wrong.

I might have spotted the issue, however i am not sure and would be happy if someone confirmed me.

It seems Unreal Engine has an assertion to make sure that no Actor would get destroyed by a class that exists in another thread.

In my case, i have a thread that runs another process. When that process gives signal, an event named BestMoveReceived is called and executes the above functions. I guess thats where the crash happens. It detects an actor is being deleted by a call from another thread and safety belt kicks in.

If there is such a thing in Unreal, then i need to search for other methods.

if you are on another thread, then you are definitely hitting a race condition :slight_smile:
you must not manipulate renderable items outside of the main (render) thread.
Try calling your code in something like this instead:

FGraphEventRef Task = FFunctionGraphTask::CreateAndDispatchWhenReady([&]() {
  // code here runs on game thread
}, TStatId(), NULL, ENamedThreads::GameThread);

// waits till task completes, you can disable this if you want
FTaskGraphInterface::Get().WaitUntilTaskCompletes(Task);

Wow, that is interesting. It works like a charm! There must be some voodoo magic involved :slight_smile:

Thanks!

I have a question, Is there any relationship between this post and this