C++ Spawning with OnOverLap called on every movement

Hi guys, so this is a really weird problem I’ve come across. The error happens if I do this in BP or in C++ (I prefer C++) so I hope someone can enlighten me to the issue.

The Goal

So I want to be able to spawn ONE tile when I step into a trigger on the object. This is for procedural terrain. Here is the code and I’ll explain it:

void ARoomTile::OnOverlapBegin(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult) {

	if (DoorSpawnTrigger != nullptr && OtherActor->ActorHasTag("Player")) {
		if (BWillSendMessage) {
			BWillSendMessage = false;
			auto GameMode = Cast<ABindingOfSynapseGameModeBase>(UGameplayStatics::GetGameMode(GetWorld()));
			GameMode->SpawnFreshTile(SpawnPositionArrow->GetRelativeTransform().GetLocation());
		}

		UE_LOG(LogTemp, Error, TEXT("Value of bool is %s"), BWillSendMessage ? TEXT("True") : TEXT("False"));
	}
}

So I’ve created a trigger known as DoorSpawnTrigger as you can see. This is created as a default subObject and has been set up correctly. I then register it to OnOverlapBegin with:

	DoorSpawnTrigger->OnComponentBeginOverlap.AddDynamic(this, &ARoomTile::OnOverlapBegin);

I do this in BeginPlay so the trigger is ready for contact with the player character.

I’ve added the BWillSendMessage to try to stop calls but it just doesn’t work, from my log it just seems to get reset constantly from true to false.

The method then called “SpawnFreshTime” simply does the following:

void ABindingOfSynapseGameModeBase::SpawnFreshTile(FVector SpawnPosition) {
	GetWorld()->SpawnActor<ARoomTile>(TileToSpawn, SpawnPosition, FRotator(0));
}

It just spawns a tile in the world at the position I want.

The Problem

From my understanding of the docs is that OnOverlapBegin should only be called when an Overlap Begins? However everytime the player moves it’s called which results in about 30+ tiles being created at once in the same place. This is obviously not the desired behaviour. I’ve been trying to debug it and I’ve found a very strange scenario.

Removing the spawn element fixes it?

When I remove the spawn argument it is officially only called once, the bool is the right value and nothing is executed. Of course this means I don’t get my tile spawned but it acts correctly for the begin overlap?

This has led me to believe that the tiles were maybe spawning in the same place? Which means every new tile would have a parameter allowing for an overlap to occur on the player, again and again. However when I check the transforms of all the other tiles.

Triggers are disabled on other tiles

Another problem is that the future tiles also have no triggers active on them. So even though of all the RoomTiles share the RoomTile class they should all be instances of that class and not a reference so I presumed the values would be fresh for each one. I’ve even compared the transforms before and after the spawning and they’re identical so there is no way the player is hitting them by accident.

Summary

Ok so if anyone can englighten me that would be great I need to know:

  1. Why on earth would On Begin Overlap be being called more than once when the new transform location never touches the player? Even then rotating in the trigger causes it to be triggered too.
  2. Is it something to do with the way spawning is done or do you believe it’s more to do with my method of spawning a new tile?

Any help would be greatly appreciated. I do like working things out alone but I’m a bit stumped here.

Cheers.

Updated: - So I just checked the names of the tiles that are hitting the player and it seems that each tile is actually hitting the player but this is happening even when I’m not in the trigger volume. Here is a glimpse from the console

I don’t fully understand your project or your goal but from the logs it looks like you are spawning a room tile, which then causes an overlap to occur, which in turn spawns another tile, creating a loop of new tiles spawning and then overlapping and then spawning, etc…

I would probably create a timer that has a small delay before binding the overlap function to the component, so there is a buffer of time before that overlap can occur.

I appreciate your comment, I actually tried this as well by disabling the Generate events for 2 seconds based on GetWorld()->GetSeconds and then I enable it. This timer does work but then it still continually loops. It’s strange how it continues to happen triggering when the new tile is never in the same position as the player.

Cheers mate, Why are you checking for the component name? I’m quite sure why in your example? Sorry if I’m being dense, been a long day. Thanks again for your response :slight_smile:

I had a similar problem and couldn’t really fix the solution of the OnComponentBeginOverlap function being executed every time when my actor is spawned dynamically from another class, even when no object is overlapped in the space. I was trying to achieve a simple operation of changing the mesh material when another component overlaps and changing back to default mesh material when OnComponentEndOverlap. These two functions were executed every tick from another class. So i decided to check the logs and change the behavior of the function. Following is an example of a work around that might help you for the time being.
//First using ‘UE_LOG(LogTemp, Warning, TEXT("%s"), *OtherComp->GetName());’ find the components that are overlapping
//Note the string of the component overlapping and check with the component string that you want

void AMyActor::Your_Function_Name(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult &SweepResult)
{
      
	FName ChkCompName = *OtherComp->GetName();
	if (ChkCompName == "ComponentTagString")
	{
		//UE_LOG(LogTemp, Warning, TEXT("%s"), *ChkCompName.ToString());
		//GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, "Entering Collision");
		//-Do

	}
}

Hope this helps.

The reason I check for component name is because:
-My actor when spawned(from another class in ‘tick’) always executed the two Overlap functions, even though no Overlap was taking place in the free space.
So component name helps me to know which component (OtherComp->GetName() is the is the tag to the component) is being overlapped, even though visually you cant differ.
I know that its a naive way of solving the problem, but that is okay, even though it might incur a minimal performance delay.

I have the same problem. Someone can explain why this happens?