Crash when destroying actor in overlap callback

Hi

I’ve noticed that I tend to get a crash in an overlap callback between 2 actors which I destory. It seems that later in the UpdateOverlaps function the engine is trying to walk down an actor to see if any of it’s children are primitives and need to be updated. The child is not valid but the null check passes because it’s set to 0xdddddddddddddddd rather than than null.

It seems one of my actors still calls Tick after Destroy is called and then a call to AddActorWorldOffset causes UpdateOverlaps to be called which crashes the engine. I even have my code wrapped inside a IsPendingKill() check.

Any idea on why this is happening? Can I not destroy actors in collision callbacks?

This is how I destory the actors

void ALuneBullet::OnBulletOverlap(UPrimitiveComponent * SelfComponent, AActor * OtherActor, UPrimitiveComponent * OtherComponent, int32 something, bool somethingElse, const FHitResult& Hit)
{
	auto WeaponOwner = WeaponOrigin ? WeaponOrigin->GetOwner() : nullptr;
	if (OtherActor && WeaponOwner && OtherActor != WeaponOwner)
	{
		this->Destroy();
		OtherActor->Destroy();
	}
}

I’ve tried adding more guards to the object that’s been destroyed from doing anything in it’s tick function but the code still executes.

void AStraightBullet::Tick(float DeltaSeconds)
{
	Super::Tick(DeltaSeconds);
	bool isActorBeingDestroyed = IsActorBeingDestroyed();
	bool isPendingKill = IsPendingKill();
	if (!isPendingKill && !isActorBeingDestroyed)
	{
		this->AddActorWorldOffset(BulletDirection * BulletSpeed, true);
	}
}

You are not destroying the current actor in the final line of code. You are actually telling the engine to do something inside of a destroyed instance (if that makes sense). Simply swap these 2 lines, it should look like: OtherActor->Destroy(); this->Destroy();

Maybe. Maybe you need more physics substep. Also check if ‘this’ and ‘OtherActor’ are not pointing to the same thing :wink:

Ah that does make sense. Unfortunately I still have the same crash if I arrange my code as follows.

void ALuneBullet::OnBulletOverlap(UPrimitiveComponent * SelfComponent, AActor * OtherActor, UPrimitiveComponent * OtherComponent, int32 something, bool somethingElse, const FHitResult& Hit)
{
	auto WeaponOwner = WeaponOrigin ? WeaponOrigin->GetOwner() : nullptr;
	if (OtherActor && WeaponOwner && OtherActor != WeaponOwner)
	{
		OtherActor->Destroy();
		this->Destroy();
	}
}

Now if I add a new method called DestroyNextTick which sets a bool indicating to call Destroy() the next time the actors tick function is called it seems to fix the issue.

The code would look like this:

void ALuneBullet::OnBulletOverlap(UPrimitiveComponent * SelfComponent, AActor * OtherActor, UPrimitiveComponent * OtherComponent, int32 something, bool somethingElse, const FHitResult& Hit)
{
	auto WeaponOwner = WeaponOrigin ? WeaponOrigin->GetOwner() : nullptr;
	if (OtherActor && WeaponOwner && OtherActor != WeaponOwner)
	{
		OtherActor->Destroy();
		this->DestroyNextTick();
	}
}

My suspicion is that 2 bullets overlap each other and then call kill on each other as well. Although it’s my understanding that calling Destroy() on an object a second time won’t do anything and will return false.

Good point. I added that check but unfortunately still no fix. I posted in the 4.12 forum thread just in case as I can’t recall having issues calling destroy in previous versions.

Of course I’d say there’s still a 90% chance it’s an error on my part :slight_smile:

So just now I opened the Epic Launcher and saw that preview version 5 was available now. I updated my engine and rebuilt now everything works with the same code. I guess there must have been a bug in 4.12.