x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

Sweep collision doesn't work if the start loc and end loc both collide with the same surface

 FCollisionQueryParams TraceParams;
 TraceParams.AddIgnoredActor(MyActor);
 TraceParams.bTraceComplex = false;
 TraceParams.bReturnPhysicalMaterial = false;

 bool Hit =GetWorld()->SweepSingleByProfile(HitOut, SphereStartLoc, SphereEndLoc, FQuat(0.0f, 0.0f, 0.0f, 1.0f), TEXT("BlockAll"), FCollisionShape::MakeSphere(Radius), TraceParams);

If SphereStartLoc and SphereEndLoc both intersect the same surface, then I either get no collision, or HitOut.Location == HitOut.ImpactPoint == SphereStartLoc. Even if just the very edge of the spheres are the only things that collide. I think I should get a proper hit location based on the sphere.

If SphereStartLoc doesn't intersect anything, but somewhere in between or at the end does, then I get a proper hit location.

HitOut.PenetrationDepth and HitOut.Normal seem to be set correctly.

In my test, I'm simply colliding with a basic cube (Modes->Place->Basic->Cube) static mesh actor.

Product Version: UE 4.11
Tags:
more ▼

asked May 16 '16 at 11:37 PM in Bug Reports

avatar image

rantrod
1.5k 47 47 213

avatar image Doug E ♦♦ STAFF May 17 '16 at 01:58 PM

Hey rantrod-

Could you provide more information on how you're setting up and testing this? Where are you including this code? What surface are you colliding with in the editor? Please include detailed steps to help reproduce the bug locally.

avatar image rantrod May 17 '16 at 09:19 PM

What surface are you colliding with in the editor?

From my post: In my test, I'm simply colliding with a basic cube (Modes->Place->Basic->Cube) static mesh actor.

Where are you including this code?

Just the Tick function for a random actor.

SphereStartLoc is a world position I get form a reference target actor. For SphereEndLoc I simply add 10.0 to Z of the start loc.

     float Radius = 35.0f;
     FVector SphereLoc = RefActor->GetActorLocation();
     FVector EndLoc = SphereLoc;
     EndLoc.Z += 10.0f;

I use DrawDebugSphere to show where I'm doing the sphere collisions and it looks exactly right:

     DrawDebugSphere(GetWorld(), SphereLoc, Radius, 12, FColor::Red, false, -1.0f);
     DrawDebugSphere(GetWorld(), EndLoc, Radius, 12, FColor::Yellow, false, -1.0f);

Collision image:

alt text

Results:

alt text

collres.jpg (46.2 kB)
spherescoll.jpg (32.2 kB)
avatar image Doug E ♦♦ STAFF May 18 '16 at 01:52 PM

Adding the code provided to a new class returns a number of compile errors. Can you provide the full code class you're using for your test so that I can ensure that my setup matches yours.

avatar image rantrod May 18 '16 at 09:14 PM

There's not much more to it. This is the full code, put it in any actor's tick function, but you do need a uparameter for the target point:

 FCollisionQueryParams TraceParams;
 TraceParams.AddIgnoredActor(this);
 TraceParams.bTraceComplex = false;
 TraceParams.bReturnPhysicalMaterial = false;
 FHitResult HitOut;

 float Radius = 35.0f;
 FVector SphereLoc = RefActor->GetActorLocation();
 FVector EndLoc = SphereLoc;
 EndLoc.Z += 10.0f;

 DrawDebugSphere(GetWorld(), SphereLoc, Radius, 12, FColor::Red, false, -1.0f);
 DrawDebugSphere(GetWorld(), EndLoc, Radius, 12, FColor::Yellow, false, -1.0f);

 FCollisionResponseParams ResponseParam;

 bool Hit = GetWorld()->SweepSingleByChannel(HitOut, SphereLoc, EndLoc, FQuat(0.0f, 0.0f, 0.0f, 1.0f), ECollisionChannel::ECC_Pawn, FCollisionShape::MakeSphere(Radius), TraceParams, ResponseParam);
 if (Hit)
 {
     DrawDebugSphere(GetWorld(), HitOut.Location, 10.0f, 12, FColor::Blue, false, -1.0f);
 }

The uparameter in the header file:

 UPROPERTY(Category = Node, EditAnywhere)
 AActor *RefActor;

So in the editor I simply set thar RefActor to a TargetPoiont. I place the TargetPoint as you see in the image with the two spheres: close to a wall such that both intersect with the same surface.

In the.cpp file of the actor you need an include for the debug draws:

 #include "DrawDebugHelpers.h"

Here's the whole class files:

link text

testcoll.zip (1.3 kB)
avatar image Doug E ♦♦ STAFF May 19 '16 at 12:54 PM

I copied the class into a new project an added an on screen debug message inside of the if(hit) condition. In the editor (third person template project) I set RefActor to the floor which printed my debug message on PIE. I then created a new blueprint with a static mesh component and added it to the viewport. When I set RefActor to the new blueprint, it too printed my debug message. Since the debug circles you're creating target the root of the actor, I tried repositioning the static mesh component and found that if the static mesh overlapped with the spheres in any amount, it would print my debug message. Here is a screenshot of my blueprint overlap.

alt text

debugsphere.png (107.9 kB)
debugsphere.png (107.9 kB)
avatar image rantrod May 19 '16 at 06:32 PM

Yes it looks like you're seeing the bug. Any idea why?

In case you've forgotten the original post, and followup comment showing the results, the problem is getting HitOut.Location == HitOut.ImpactPoint == SphereLoc

I can see in your image, the blue sphere in the middle should be at the intersection point, but instead it's in the incorrect location -- the SphereLoc.

When doing a sphere collision test, I need to know where the intersection point is. Penetration Depth and normal are not enough to calculate an intersection point because there are multiple symmetrical possibilities for any given penetration depth and normal.

All other collision calls give you a proper intersection point, except for the sweep functions. Is there a fix for this?

(comments are locked)
10|2000 characters needed characters left

1 answer: sort voted first

Hey rantrod-

I have entered a report for the behavior of Hit.Location and Hit.ImpactPoint when using a sweep sphere, UE-31047 .

Cheers

Doug Wilson

more ▼

answered May 19 '16 at 09:15 PM

avatar image LEGO_MANIAC STAFF May 23 '16 at 05:05 PM

This is not a bug, the screenshot shows that "bStartPenetrating=true", meaning the sphere started in penetration. We don't have enough info in this case to provide a meaningful impact point because it's a whole collection of points along the surface of the object.

I will update the documentation for FHitResult to make this clearer.

avatar image rantrod May 24 '16 at 09:18 PM

Couldn't you return the closest point of intersection? It's what a normal sphere vs world test does in other engines. Is there a simple sphere vs world check in UE4 (C++)?

avatar image LEGO_MANIAC STAFF May 24 '16 at 09:26 PM

It's possible to get this data, if you want to run another query (or multiple queries in the case of multiple overlapped shapes), though there are still failure cases or you might want even more info (point, normal, etc). Plus there is a potentially large hidden performance cost here so we don't do this automatically.

We've recently added UBodySetup::GetClosestPointAndNormal() to the code, which could help.

(comments are locked)
10|2000 characters needed characters left
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question