/** * Perform some collision sweep tests. Creates a given shape mesh and checks collision normal against a collision shape type. * Data for tests is in the [/Script/UnrealEd.CollisionAutomationTestConfigData] section of BaseEditor.ini * * @param Parameters - Unused for this test * @return TRUE if the test was successful, FALSE otherwise */ bool FComponentSweepMultiTest::RunTest(const FString& Parameters) { CollisionAutomationTests::TestBase = this; // Create map UWorld* World = FAutomationEditorCommonUtils::CreateNewMap(); TestNotNull( TEXT("Failed to create world for Physics.Collision.Ray Test. Tests aborted."), World ); static FName TraceIdent = FName(TEXT("TestTrace")); FVector StartPos; FVector EndPos; ECollisionChannel Channel = ECC_WorldStatic; UCollisionAutomationTestConfigData* Data = UCollisionAutomationTestConfigData::StaticClass()->GetDefaultObject<UCollisionAutomationTestConfigData>(); // Get the tests for (int32 iTest = 0; iTest < Data->ComponentSweepMultiTests.Num(); iTest++) { FCollisionTestEntry OneElement = Data->ComponentSweepMultiTests[iTest]; // Create the Actor to check against AStaticMeshActor* TestRayMeshActor = CollisionAutomationTests::CreateShapeMeshActor( *OneElement.RootShapeAsset, OneElement.HitResult.TraceEnd); // Create the collision component AActor* TestRayCollisionActor = CollisionAutomationTests::CreateCollisionShape( World, OneElement.ShapeType, OneElement.HitResult.TraceStart); if ((TestRayMeshActor != nullptr) && (TestRayCollisionActor != nullptr)) { // Set the collision profile and enable collision and physics TestRayMeshActor->GetStaticMeshComponent()->BodyInstance.SetCollisionProfileName(TEXT("BlockAll")); TestRayMeshActor->SetActorEnableCollision(true); TestRayMeshActor->GetStaticMeshComponent()->BodyInstance.bSimulatePhysics = true; UShapeComponent* CollisionComponent = Cast<UShapeComponent>(TestRayCollisionActor->GetRootComponent()); TestRayCollisionActor->SetActorEnableCollision(true); if( CollisionComponent != nullptr ) { CollisionComponent->SetCollisionProfileName(TEXT("BlockAll")); CollisionComponent->SetSimulatePhysics(true); } // Setup positions StartPos = TestRayCollisionActor->GetActorLocation(); EndPos = TestRayMeshActor->GetActorLocation(); // Setup the query FComponentQueryParams ShapeQueryParameters(TraceIdent, nullptr); ShapeQueryParameters.bTraceComplex = true; ShapeQueryParameters.bTraceAsyncScene = true; // Perform test TArray<FHitResult> OutHits; bool WasBlocked = World->ComponentSweepMulti(OutHits, CollisionComponent, StartPos, EndPos, FRotator::ZeroRotator, ShapeQueryParameters); bool BlockedBySpecified = false; if (WasBlocked == true) { for (int32 iHits = 0; iHits < OutHits.Num(); iHits++) { AActor* EachActor = OutHits[iHits].GetActor(); if (EachActor == TestRayMeshActor) { BlockedBySpecified = true; // This generates a snippet you can copy/paste into the ini file for test validation //UE_LOG(CollisionAutomationTestLog, Log, TEXT("%d:HitResult=(%s)"), iTest+1, *(CollisionAutomationTests::HitToString(OutHits[iHits]))); CollisionAutomationTests::CheckVector( OutHits[iHits].ImpactNormal, OneElement.HitResult.ImpactNormal, TEXT("ComponentSweepMulti"), TEXT("ImpactNormal"), iTest ); CollisionAutomationTests::CheckVector( OutHits[iHits].Normal, OneElement.HitResult.Normal, TEXT("ComponentSweepMulti"), TEXT("Normal"), iTest ); CollisionAutomationTests::CheckVector( OutHits[iHits].ImpactPoint, OneElement.HitResult.ImpactPoint, TEXT("ComponentSweepMulti"), TEXT("ImpactPoint"), iTest ); CollisionAutomationTests::CheckFloat( OutHits[iHits].Time, OneElement.HitResult.Time, TEXT("ComponentSweepMulti"), TEXT("Time"), iTest ); } } } TestTrue(FString::Printf(TEXT("Test %d:ComponentSweepMulti from %s to %s failed. Should return blocking hit"), iTest+1, *TestRayMeshActor->GetName(), *TestRayCollisionActor->GetName()), BlockedBySpecified); } // Remove the actors TestRayMeshActor->Destroy(); TestRayCollisionActor->Destroy(); } return true; }