Download

Detect Collision of Dungeon Modules during generation

Hello everyone,
I am working on my game development project and built a basic modular dungeon generator. My problem now is that modules get spawned like a tree and at some point they will overlap each other which im trying to prevent by detecting a collision and trying a different module to connect at specific exitpoint.
All my modules are blueprint classes that inherit from my base C++ class AModule and then get assigned different meshes and exitpoints via blueprints. I cant seem to figure out how to detect collision in my C++ code. I would like to fire an event that gets then processed during runtime by my generator.

If you spawn it there’s a collision parameter (spawn always - ignore collision, reposition on collision, …) could this be a usable way?
Or you could use a position based grid system, so overlapping isn’t possible - at least if the module sizes dont exceed the grid “tile” size.

Currently my Algorithm looks like this



if (world){
		//spawn starting module
		AActor* startModule = GetWorld()->SpawnActor<AModule>(m_startModule, FVector(0.f, 0.f, 0.f), FRotator(0.f, 45.f, 0.f), spawnParams);

		//get components from startmodule and paste in array
		TArray<UChildActorComponent*> pendingExits;
		startModule->GetComponents(pendingExits);

		//the dungeon algorithm
		for (int32 x = 0; x < m_iterrations; x++)
		{
			TArray<UChildActorComponent*> newExits;
			for (int i = 0; i < pendingExits.Num(); i++)
			{
				//get random tag from i-th component
				FName tag = pendingExits*->ComponentTags[FMath::RandRange(0, pendingExits*->ComponentTags.Num() - 1)];
				//spawn new module at dummy location
				FVector dummyLocation;
				dummyLocation.Set(0, 0, -100);
				//init to prevent error
				AModule* newModule = GetWorld()->SpawnActor<AModule>(m_test, dummyLocation, FRotator::ZeroRotator, spawnParams);
				newModule->Destroy();


				//TODO
				// *try to place without collision to other modules
				// *if fail try again
				// *if success proceed
				// *if fails try with different module for *specified times* 
				//		or end here and mark as not connected


				//chose random module
				//spawn module matching the random tag
				if (tag == "corr")
				{
					int num = FMath::RandRange(0, m_corrs.Num() - 1);
					newModule = GetWorld()->SpawnActor<AModule>(m_corrs[num], dummyLocation, FRotator::ZeroRotator, spawnParams);
				}
				else if (tag == "junc")
				{
					int num = FMath::RandRange(0, m_juncs.Num() - 1);
					newModule = GetWorld()->SpawnActor<AModule>(m_juncs[num], dummyLocation, FRotator::ZeroRotator, spawnParams);
				}
				else if (tag == "room")
				{
					int num = FMath::RandRange(0, m_rooms.Num() - 1);
					newModule = GetWorld()->SpawnActor<AModule>(m_rooms[num], dummyLocation, FRotator::ZeroRotator, spawnParams);
				}

				//get new module exits
				TArray<UChildActorComponent*> newModuleExits;
				newModule->GetComponents(newModuleExits);
				//choose random exit
				AActor* exitToMatch = newModuleExits[FMath::RandRange(0, newModuleExits.Num() - 1)]->GetChildActor();
				//match exits
				MatchExits(pendingExits*->GetChildActor(), exitToMatch);
				//get remaining unconnected exits from new module
				for (int e = 0; e < newModuleExits.Num(); e++)
				{
					if (newModuleExits[e]->GetChildActor() != exitToMatch)
						newExits.Add(newModuleExits[e]);
				}
				//add placed verified module to array
				m_dungeonModules.Add(newModule);
				newModule = NULL;
			}
			//update pending exits
			pendingExits = newExits;
		}
		//TODO
		//* mark all unconnected exits and place *defined object*
}


I want to give my Artist as much freedom as possible thats why I dont want to implement a tile based system. My artists will be creating the rooms directly in the 3D modelling software. And the collision parameter would not work in this scenario as my modules get spawned to a dummylocation and afterwards rotated and translated to where they should be inside of the


void ADungeonController::MatchExits(AActor* exit1, AActor* exit2)

function

If you have a List of the modules you want to check collision against, you could simply call GetActorBounds and then construct an FBox object and do an AABB test using the FBox methods. If you don’t have a list, you could just use the UWorld object and call OverlapAnyTestByChannel(…).

Thank you. I will try that right away. And give feedback on whether it worked or not :slight_smile: