So im working on a template based level generator and i got most of it working except for a small issue
Currently im using this on my own PCManager class
“PCManager.cpp”
#include "PCGame.h"
#include "PCRoom.h"
#include "RoomStartPoint.h"
#include "RoomEndPoint.h"
#include "PCManager.h"
UPCManager::UPCManager(const class FPostConstructInitializeProperties& PCIP)
: Super(PCIP)
{
}
TSubclassOf<class APCRoom> UPCManager::GetRandomRoom(bool bSpawnRoom)
{
int32 RandomRoomIdx = FMath::RandRange(0, CurrentTheme.LinkedRooms.Num()); // first get a random room
if (CurrentTheme.LinkedRooms.IsValidIndex(RandomRoomIdx) == true) // if our index is valid
{
if (bSpawnRoom == true)
{ // TODO:Make the spawn room random!
if (CurrentTheme.LinkedRooms[0]->GetDefaultObject<APCRoom>()->bIsSpawnRoom) // And the room is marked as a spawn room
{
return CurrentTheme.LinkedRooms[0]; // then return this random room
}
}
else
{
RandomRoomIdx = RandomRoomIdx = FMath::RandRange(0, CurrentTheme.LinkedRooms.Num()); // first get a random room
if (CurrentTheme.LinkedRooms.IsValidIndex(RandomRoomIdx) == true) // if our index is valid
{
if (CurrentTheme.LinkedRooms[RandomRoomIdx]->GetDefaultObject<APCRoom>()->bSpawned == false) // if the room hasnt been spawned
{
if (CurrentTheme.LinkedRooms[RandomRoomIdx]->GetDefaultObject<APCRoom>()->bIsSpawnRoom == false) // and its not an spawn room
{
return CurrentTheme.LinkedRooms[RandomRoomIdx];
}
}
}
}
}
return NULL;
}
void UPCManager::InitGeneration()
{
bool bSpawnedInitialRoom = false;
FVector SpawnLoc;
FRotator TheRot;
FActorSpawnParameters SpawnInfo;
FVector PrevRoomLoc;
FVector SpawnPoint, EndPoint;
TObjectIterator<APlayerController> ThePC;
if (!ThePC) return;
PCWorld = ThePC->GetWorld();
if (bGenerateFullLevelOnStart) //
{
FVector AlignLoc;
TSubclassOf<APCRoom> RoomToSpawn = GetRandomRoom(true); //
int32 RoomIdx = CurrentTheme.LinkedRooms.Find(RoomToSpawn);
for (TActorIterator<APlayerStart> ActorItr(PCWorld); ActorItr; ++ActorItr) //
{
RoomToSpawn = CurrentTheme.LinkedRooms[0];
APCRoom* T = PCWorld->SpawnActor<APCRoom>(RoomToSpawn, ActorItr->GetActorLocation(), ActorItr->GetActorRotation(), SpawnInfo); // Spawn the room
SpawnedRooms.Add(T);
if (CurrentTheme.LinkedRooms.IsValidIndex(RoomIdx)) // Make sure the index is valid before accessing it
{
CurrentTheme.LinkedRooms[RoomIdx]->GetDefaultObject<APCRoom>()->bSpawned = true; // we spawned this room so mark it as that
}
GeneratedRoomsForTheme = CurrentTheme.MaxRoomsForTheme;
UE_LOG(LogTemp, Warning, TEXT("Spawned the spawn room"));
break;
}
for (int32 i = 0; i < CurrentTheme.MaxRoomsForTheme; i++) //Loop for all the rooms that the level should have
{
TArray<USceneComponent*> comps; // Store a array for the first component
TArray<USceneComponent*> proomcomps; // Store previous room components
TSubclassOf<APCRoom> NewRoom = GetRandomRoom(false); // Get a Random Normal Room to spawn next to the spawn room
CurrentRoom = PCWorld->SpawnActor<APCRoom>(NewRoom, FVector(0,0,0), TheRot, SpawnInfo); // Spawn the New Room next to the spawn room
SpawnedRooms.Add(CurrentRoom); // add the new room to the array
UE_LOG(LogTemp, Warning, TEXT("Spawned a new Current Room"));
PreviousRoom = SpawnedRooms[SpawnedRooms.Num() - 1]; //(Crashing Here)
// So we can properly offset it
PreviousRoom->GetComponents(comps); // loop trough all the "Previous room" components and get its ending point
for (auto Components : comps) // get the spawn location for the new room
{
URoomEndPoint* SpawnPo = Cast<URoomEndPoint>(Components);
if (SpawnPo)
{
SpawnPoint = SpawnPo->GetComponentLocation();
break;
}
}
CurrentRoom->GetComponents(comps); // Loop trough the current room and set its start point / root to the new location
for (auto Components : comps) // get the spawn location for the new room
{
URoomStartPoint* EndPointsz = Cast<URoomStartPoint>(Components);
if (EndPointsz)
{
EndPointsz->SetWorldLocation(SpawnPoint);
break;
}
}
}
As it can be seen i first spawn a "Spawn room " at the level player start actor, i add the spawned room to a array so i can keep a track of it, now based on a int ( MaxRoomsPerTheme ) i loop and spawn a set of random rooms in no order and add them to the array, Now since they need to be aligned
I Get the "Ending Point " ( Custom actor placed in the blueprint ) Which holds the location of where the Room ends / space where the next room can be spawned on , The issue is that when i try to access the previous room ( SpawnedRooms.Num() - 1 ) , The editor crashes i Logged the array length and it is greather than 1 so it cant be invalid…