Download

Cumulative offset error when setting actor location

Hey guys, so I coded an infinite moving grid system that simulates an infinite runner by recycling types that have passed the player and moving them to the front of the grid. this worked great until I added horizontal movement. For some reason, a gap appears between the tiles over time that grows when I move the tiles horizontally, and I can’t figure out where the issue would be.Anyone have an idea? The horizontal movement code is located inside the ResetPastTiles function. Thanks for the help



// Called when the game starts or when spawned
void AGridManager::BeginPlay()
{
	Super::BeginPlay();
	PopulateGrid();
	PlaceTiles();
	GenerateSpawnLocations();
	StartMovement();
}

// Called every frame
void AGridManager::Tick( float DeltaTime )
{
	Super::Tick( DeltaTime );
	ResetPastTiles();
}

void AGridManager::PopulateGrid()
{
	//Initialize Tiles
	groundTiles = TArray<TArray<AGroundTile*>>();

	//Populate 2D array of tiles
	for (int i = 0; i < gridHeight; i++)
	{
		TArray<AGroundTile*> tempArray = TArray<AGroundTile*>();
	
		for (int i = 0; i < gridWidth; i++)
		{
			AGroundTile* tempTile = GetWorld()->SpawnActor<AGroundTile>(AGroundTile::StaticClass());
			UStaticMeshComponent* tileMeshComponent = (UStaticMeshComponent*)tempTile->GetComponentByClass(UStaticMeshComponent::StaticClass());
			tileMeshComponent->SetStaticMesh(tileTypes[0]);

			tempArray.Add(tempTile);

		}
		groundTiles.Add(tempArray);
	}

	leftTileColumn = 0;
	rightTileColumn = gridWidth - 1;
}

void AGridManager::PlaceTiles()
{
	tileSize = FVector();

	for (int i = 0; i < gridHeight; i++)
	{
		for (int j = 0; j < gridWidth; j++)
		{
			AGroundTile* tempTile = groundTiles*[j];
			//Generate position for new Tile
			float xOffset = i + 1;
			float yOffset = j + 1;
			FVector tileOrigin = FVector();
			tempTile->GetActorBounds(false,tileOrigin,tileSize);

			FVector tileLocation = FVector(GetActorLocation());
			tileLocation.X += xOffset * tileSize.X * 2;
			tileLocation.Y += yOffset * tileSize.Y * 2;

			tempTile->SetActorLocation(tileLocation);
		}
	}
	leftEdge = groundTiles[0][0]->GetActorLocation().Y - tileSize.Y * 2;
	rightEdge = groundTiles[0][0]->GetActorLocation().Y + gridWidth * tileSize.Y + (tileSize.Y * 2);

}

void AGridManager::StartMovement()
{
	for (int i = 0; i < gridHeight; i++)
	{
		for (int j = 0; j < gridWidth; j++)
		{
			groundTiles*[j]->MoveSpeed = MoveSpeed;
			groundTiles*[j]->StartMoving();
		}
	}
}

void AGridManager::GenerateSpawnLocations()
{
	for (int i = 0; i < gridWidth; i++)
	{
		FVector location = groundTiles[gridHeight - 1]*->GetActorLocation();
		AActor* newSpawnActor = GetWorld()->SpawnActor<AActor>(AActor::StaticClass());
		USceneComponent* sceneComponent = NewObject<USceneComponent>(newSpawnActor);
		sceneComponent->RegisterComponent();
		newSpawnActor->SetRootComponent(sceneComponent);

		newSpawnActor->SetActorLocation(location);
		spawnLocations.Add(newSpawnActor);
	}
}

void AGridManager::ResetPastTiles()
{
	//Move tiles that have passed the farther point of the grid system back to the top
	if (groundTiles[closestTileRow][0]->GetActorLocation().X <= GetActorLocation().X)
	{
		for (int i = 0; i < gridWidth; i++)
		{
			groundTiles[closestTileRow]*->SetActorLocation(spawnLocations*->GetActorLocation());
		}
		closestTileRow++;
		if (closestTileRow >= gridHeight)
		{
			closestTileRow = 0;
		}
	}
	//Move tiles that have gone too far left back to the right edge
	if (groundTiles[0][leftTileColumn]->GetActorLocation().Y < leftEdge)
	{

		spawnLocations[leftTileColumn]->SetActorLocation(FVector(spawnLocations[leftTileColumn]->GetActorLocation().X, rightEdge, GetActorLocation().Z));
		UE_LOG(LogTemp, Warning, TEXT("RIGHT MOVE"));
		for (int i = 0; i < gridHeight; i++)
		{
			groundTiles*[leftTileColumn]->SetActorLocation(FVector(groundTiles*[leftTileColumn]->GetActorLocation().X, spawnLocations[leftTileColumn]->GetActorLocation().Y, GetActorLocation().Z));

		}

		rightTileColumn = leftTileColumn;
		leftTileColumn++;

		if (leftTileColumn >= gridWidth)
		{
			leftTileColumn = 0;
			rightTileColumn = gridWidth - 1;
		}
	}
	//Move tiles that have gone too far right back to the left edge
	if (groundTiles[0][rightTileColumn]->GetActorLocation().Y > rightEdge)
	{

		spawnLocations[rightTileColumn]->SetActorLocation(FVector(spawnLocations[rightTileColumn]->GetActorLocation().X, leftEdge, GetActorLocation().Z));
		UE_LOG(LogTemp, Warning, TEXT("LEFT MOVE"));
		for (int i = 0; i < gridHeight; i++)
		{
			groundTiles*[rightTileColumn]->SetActorLocation(FVector(groundTiles*[rightTileColumn]->GetActorLocation().X, spawnLocations[rightTileColumn]->GetActorLocation().Y, GetActorLocation().Z));
		}


		leftTileColumn = rightTileColumn;
		rightTileColumn--;

		if (rightTileColumn < 0)
		{
			leftTileColumn = 0;
			rightTileColumn = gridWidth - 1;
		}
	}
}

void AGridManager::TranslateTiles(float input)
{
	input *= HorizontalMoveSpeed;

	for (int i = 0; i < gridHeight; i++)
	{
		//Translate spawn Locations
		FVector location = FVector(spawnLocations*->GetActorLocation().X, spawnLocations*->GetActorLocation().Y - input * GetWorld()->GetDeltaSeconds(), spawnLocations*->GetActorLocation().Z);
		spawnLocations*->SetActorLocation(location);

		for (int j = 0; j < gridWidth; j++)
		{
			groundTiles*[j]->MoveHorizontal(input);
		}
	}
}


bump for desperation

figured it out, the variations in delta time between frames was causing the conditional to be triggered slightly over the reset value. Fixed it myself by redoing the entire code and basing it off a master tile so gaps would be an impossibility.