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"

Office Holiday

Epic Games' offices will be on holiday from June 22nd to July 7th. During this period support will be limited. Our offices will reopen on Monday, July 8th. 

UPrimitiveComponent::GetClosestPointOnCollision returns points not on the UPrimitiveComponent's collision

UPrimitiveComponent::GetClosestPointOnCollision is currently returning points which are not on the collision of the Primitive Component which called GetClosestPointOnCollision, but which is on collision belonging to other components which are children of the same actor.

Repro: In a simple first-person template map: Add this actor (It's a .COPY export renamed as a .txt because these forums don't like .copys)

Product Version: UE 4.14
Tags:
more ▼

asked Dec 02 '16 at 05:32 PM in Bug Reports

avatar image

Teiwaz
629 26 29 55

avatar image Doug E ♦♦ STAFF Dec 05 '16 at 03:19 PM

Hey Teiwaz-

Can you provide screenshots of the behavior you're seeing and the setup you're using? I tried to recreate the issue based on the steps provided and I am only seeing a single debug point rather than two. Here is how I'm setting up the blueprint and an image of the outcome in the editor. Let me know if you're using a different setup for your test.

alt text alt text

debugpoint.png (555.0 kB)
avatar image Teiwaz Dec 05 '16 at 03:57 PM

Ugh, sorry. My actual use case is done in code, which is much harder to share. I assumed the blueprint version would be equivalent, since I'm calling the same function that is exposed in blueprint. I'll dig into this more and see if I can figure out the discrepancy between the code and the blueprint.

To clarify, though, the behavior I'm seeing isn't that there are multiple points, it's that the one point that's being returned is on collision not belonging to the StaticMeshComponent I'm calling GetClosestPointOnCollision on.

Basically, I'm checking GetClosestPointOnCollision on multiple component meshes belonging to the same actor to find the sub-component closest to an external point. But instead of multiple checks to different meshes, I'm getting every sub-component returning the same distance, and when I draw the point that's being returned, all the distance checks are being made to the same point. That point can be on any of the collisions of any of the static meshes on the object, so it's not that I'm calling GetClosestPointOnCollision on the wrong mesh. It seems to be combining all of the collisions on all of the meshes before doing the check.

I'll let you know if I can repro it in isolation.

avatar image Teiwaz Dec 05 '16 at 04:11 PM

Okay, I figured it out. The problem occurs when the mesh you're checking is the child component of another mesh which is set to simulate physics. If you check for the closest point on collision of any static mesh component child of a physics simulating static mesh component, then the point returned can be on any of the children of the physics simulating mesh or on the simulating mesh itself.

So the full repro is:

  • In a simple first-person template map:

  • Create a new blueprint actor.

  • Add a static mesh component to the actor as the root component. Set its mesh to be a 1m cube, and check "simulate physics" on it.

  • Add two static mesh components to the actor as children of the cube. Set their meshes to be cylinders, and drag them apart.

  • On tick, call GetClosestPointOnCollision on one of the cylinder child components to get the closest point on one of the cylinders to the player camera. Draw a debug point there.

  • Place the blueprint in a test level and run it.

  • Move around the blueprint. Observe that the drawn debug point will draw on whichever collision is closer to the player, even though only one of the cylinder is looking for the closest point on its collision. (The point will jump back and forth between them as the player moves around.)

I believe this is due to PhysX combining all the collision primitives of physically simulated objects. If you start digging down in the GetClosestPointOnCollision code, you'll find that it uses PhysX to provide all collision bodies on the physics actor. PhysX is presumably combining all of the bodies associated with a physics simulating component into a single physics actor for simulation purposes, so it's returning all of the children when asked.

I added a .COPY of the test actor I used here (It's a .COPY export renamed as a .txt because these forums don't like .copys)

The yellow cylinder is the one which is being checked for the closest point.

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

1 answer: sort voted first

Hey Teiwaz-

Thank you for the additional information. This does indeed appear to be tied to the simulate physics setting as calling this node for a component that is not below the simulate physics set component still function as expected. I have entered a ticket for this issue that you can find here: https://issues.unrealengine.com/issue/UE-39329 . You can track the report's status as the issue is reviewed by our development staff. Please be aware that this issue may not be prioritized or fixed soon.

Cheers

Doug Wilson

more ▼

answered Dec 05 '16 at 05:17 PM

avatar image Teiwaz Dec 06 '16 at 08:57 PM

More info from my search for a workaround:

If you turn off bAutoWeld on the child components, their collision is no longer merged into the parent for the purposes of the nearest collision check.

However, their collision no longer matters at all for physics purposes when their parent simulates physics. But it's a pretty clear indicator that the bodies being combined for physics simulation purposes is the culprit causing this problem.

There's a function on UPrimitiveComponent called GetBodyInstance which has a "bWelded" parameter which is true by default, and looks like it should return the actual body instance of the UPrimitiveComponent rather than its weld parent (which would let me call GetDistanceToBody, which is what GetClosestPointOnCollision ultimatley calls, just on the wrong thing) but the FBodyInstance returned when bWelded is false doesn't appear to be valid. I'm assuming this is because it never has a body created for it since everything it does would be handled by the weld parent, and I can't seem to find any straightforward way of making it generate one anyway.

avatar image Teiwaz Dec 06 '16 at 09:36 PM

Okay, that led to an acceptable temporary workaround. Immediately before I do the collision distance check, I unweld the primitivecomponent, then do the check, and then re-weld it immediately afterwards. It's probably bad for performance to futz with physics like that, but keeps me moving for now.

(comments are locked)
10|2000 characters needed characters left
Viewable by all users
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