Download

Sweep for Collision before Spawn

**I was wondering the best way to check the area for collisions before spawning an object, certain variables and commands suggest there might be an easy way to do this.
such as **


SpawnInfo.bNoCollisionFail = false;

If there is no easy way, is the best way to grab the Actor out of the UClass and find its size, (maybe using GetActorBounds, although i cant work out how to use this.) then sweep the area with those dimensions?

Not totally relevant but this is what i have so far


					UClass* newModulePrefab = (UClass*) GetRandomWithTag(Modules, newtag);
					//Now to test COLLISION!
					AModule* mod = newModulePrefab->GetDefaultObject; //Convert the UClass to an Actor to get its size and make a box.

//Now find the bounds of the actor and make a FBox out of it, then check for collision........

					newmod = World->SpawnActor<AModule>(newModulePrefab, pendingexit->GetActorLocation(), SpawnRotation, SpawnInfo);

Found a solution, but its ugly.
Basically i spawn the actor then use Overlapping actors, if it finds one (and casts it to see if its the same class) it removes the spawned actor.

This is not a good solution because im sure its not optimal to spawn an actor just to check if it will collide with things.

Questions:
** 1.** Using GetOverlappingActors filter, how do i declare a class type. eg GetOverlappingActors(OutActors, ‘class AActor’) // What is the syntax for only looking at AActors that are overlapping? i can find all and then cast them but this seems less optimal.

2. How bad is this method to spawn and check collision? This is for a level generator and it will try 5 times with random set pieces till it finds one that fits over man iterations, so it will be looped alot, but only during BeginPlay().

3. In the code below i use Unique ID’s to check the pieces against each other, is this a valid method ? From my tests it seems to work fine for now.

Thanks


				
newmod->GetOverlappingActors(OutActors);
for (AActor* OverActor : OutActors)
{

	AModule* casttest = Cast<AModule>(OverActor);
	if (casttest != NULL)
	{
		if (OverActor->GetUniqueID() != newmod->GetUniqueID() && OverActor->GetUniqueID() != pendingexit->GetAttachParentActor()->GetUniqueID()) //Is not itself AND is not from its pending exit.
		{
			//WE GOT AN OVERLAP, call the police.
			FoundSolution = false;
		}
	}

}

This https://docs.unrealengine.com/latest/INT/Programming/UnrealArchitecture/Actors/Spawning/index.html is probably what you need. Pass in false for bNoCollisionFail.

You can use something like GetWorld()->OverlapMulti to do a collision test. You can’t test for specific classes, but you can look for specific ‘object types’ and then filter the results yourself. I talk about that a bit here: Collision Filtering - Unreal Engine

You don’t need to compare ‘UniqueID’ to see if Actors are the same, you can just compare pointers!

Passing in false for bCollisionNoFail causes the engine to call UWorld::FindTeleportSpot() if the initial locaiton fails due to collision, and it tries a sequence of adjusted positions (through UWorld::EncrachingBlockingGeometry()) to find a non-overlapping spot.

How do you compare pointers? If I compare the iterator to the Actor* of my Actor I get a compile error. I tried Casting but compiler wouldn’t allow that either. And UniqueID doesn’t seem to work reliably. The iterator’s UniqueID doesn’t match my Actor’s UniqueID when they are in fact the same Actor.

I figured out why GetUniqueID wasn’t working. Need to also check the Role. Here’s the code that works (I’m checking to make sure I can’t spawn a new portal that overlaps another portal):

int32 newPortalID = newPortal->GetUniqueID();
ENetRole newPortalRole = newPortal->Role;
newPortal->GetActorBounds(false, portalOrigin, portalExtent);
FBox newPortalBBox(portalOrigin - portalExtent, portalOrigin + portalExtent);

for (TObjectIterator<APortal> pItr; pItr; ++pItr) {
[INDENT][/INDENT]if (newPortalRole != pItr->Role || newPortalID == pItr->GetUniqueID()) continue;

[INDENT][/INDENT]pItr->GetActorBounds(false, portalOrigin, portalExtent);
[INDENT][/INDENT]FBox otherPortalBBox(portalOrigin - portalExtent, portalOrigin + portalExtent);
[INDENT][/INDENT]if (newPortalBBox.Intersect(otherPortalBBox)) {
[INDENT][INDENT][/INDENT][/INDENT]newPortal->Destroy();
[INDENT][/INDENT]}
}