Download

How to properly Destroy() an Object? Destroy() results in editor crash.

How to properly delete a pointed to Actor?


void AAIHordeHandler::Tick(float DeltaSeconds)
{
	Super::Tick(DeltaSeconds);
	//GEngine->AddOnScreenDebugMessage(-1, 2, FColor::Red, TEXT("WORKING"));

	UWorld* const World = GetWorld();
	for (TObjectIterator<AAIEnemy> Itr; Itr; ++Itr)
	{
		for (TObjectIterator<AAIEnemy> ItrOther; ItrOther; ++ItrOther)
		{
			float itrDist = Itr->GetDistanceTo(*ItrOther);
			if (Itr->GetName() != ItrOther->GetName() && itrDist <= 750) {
				if (Itr->GetIsHorde() && ItrOther->GetIsHorde())
				{
					if (!Itr->GetInHorde() && !ItrOther->GetInHorde()){
						Itr->HordeContainer = World->SpawnActor<AAIHordeContainer>();                            //HordeContainer object is created here
						ItrOther->HordeContainer = Itr->HordeContainer;
						Itr->HordeContainer->AddMember(*ItrOther);
						Itr->HordeContainer->AddMember(*Itr);
					}
					else if (!Itr->GetInHorde() && ItrOther->GetInHorde()){
                                               //Adds ItrOther to existing HordeContainer
					}
					else if (Itr->GetInHorde() && ItrOther->GetInHorde()){
						//Check if in same Horde
						//Merge Hordes or steal members                   /* -- NEED TO DESTROY ItrOther->HordeContainer after merging the TArrays. 
                                                                                                                Calling ItrOther->HordeContainer.Destroy() results in crash.*/
					}
				}
			}
		}
	}
}

Can you provide the call stack for the crash? Calling Destroy() should in theory be the right thing to do to mark the Actor as destroyed. I do wonder if you’re causing your object iterators to get corrupted. I would also recommend that you use TActorIterator instead of TObjectIterator. In play in editor your function is going to find objects in the editor world, not just those in your play world, which would likely be problematic.

I’ll get it when I get home from work in about 6 1/2 hours :\

Will TActorIterator not find objects in the editor world?

Are you able to debug the code and does it crash on the actual Destroy function, or are you attempting to access the same memory location via another pointer further in the code? If it is on the Destroy() function that you are crashing, then I would also recommend checking if you are already pending to destroy the actor : if (!Object->IsPendingKill()) { then destroy it }, just to be sure.

Another silly question I have that I’m sure anyone can answer…

How do you change the tick rate of the function? I don’t need this to tick every frame. Every second would probably suffice. Not entirely sure where I’m supposed to set DeltaSeconds though.

This is slightly older code so the Destroy call isn’t present here. I don’t have access to current code as I’m at work. The only difference is that I can join others to existing Groups, and I started working on Merging groups. If I comment out the Destroy() line there is no crash. I will likely put a Destroy function on my HordeContainer so that I call Destroy from the object itself. This should allow my Handler to continue iterating in the case where the destroy is pending.

TActorIterator takes a world as a parameter indicating which world to look at the Actors from.

Hm, I’ve spotted some issues in your code. You could be using DistanceSquared instead of DistanceTo() (assuming it’s doing a squared length comparison). Hopefully that Name comparison is doing a Hash compare and not a string compare (assuming that’s an FName). Also do a pointer compare and early out to make sure it’s not same object. Right now you pull distance even for the exact same object 1st.

Hard to say why your Destroy() crashes without a call stack.

Everything is working at the moment. TActorIterator fixed the Destroy issue it seems. I also have them pathing now through a behavior tree. The HordeContainers are building and destroying properly as new group members are added. Next up I will make them issue a new move command (to a random point in radius of new target position) to all group members on MoveTo complete. This will make them walk together with their group.

Some of the things I have coded are just “GET IT DONE NOW” solutions. I had problems before with other solutions, most likely due to using TObjectIterator instead of Actor. I need to go back through and change things like DistanceSquared and check pointers on Actors instead of names.

Thanks a lot for the input! You helped remind me to go back and change those things.