Search Unity

We need a way to detect and resolve collision hits manually

Discussion in 'Physics' started by PhilSA, Jan 15, 2016.

  1. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    EDIT:
    There's been lots of varying discussions/questions/solutions in this thread over the last year, so I'm gonna try to sum everything up:

    Making character controllers in Unity is currently very frustrating. We do not have access to what we need in order to make "perfect" kinematic character controllers. Nvidia explains better than me why non-kinematic rigidbody character controllers have problems: http://docs.nvidia.com/gameworks/co...ntrollers.html#kinematic-character-controller

    Basically, we need access to methods that would allow us to probe the environment for nearby colliders and resolve the collisions by ourselves, with custom code. In other words; we need to be able to collect collision information and THEN apply movement to the rigidbody. All in the same fixed update. Currently, this is impossible in Unity, because collision info can only be accessed through OnCollisionX(), which always occurs after the FixedUpdate, so any attempts to react to collision information will always occur in the next physics update, with a noticeable delay.

    What we need is access to PhysX's "computePenetration" method (see "Penetration depth" section): http://docs.nvidia.com/gameworks/content/gameworkslibrary/physx/guide/Manual/GeometryQueries.html (thanks to EnokStenhuggare for the link). So our hypothetical Character Controller would be a kinematic rigidbody and would do something like this in its FixedUpdate():
    1. Collect all nearby colliders using OverlapCapsule
    2. Test penetration against each of these colliders with "computePenetration"
    3. Manually resolve collisions using the computed penetration information of step 2
    4. Use penetration information of step 2 to also determine things like "grounding" status, slope angles, obstruction normals, snapping to ground surface, etc.... (Normally I'd use a downward spherecast with a small upwards offset for this, but now we can hit two birds with one stone)
    5. Do regular character movement handling (Move the kinematic rigidbody at a certain velocity with a sweep test to preemptively detect movement collisions, etc....)
    The manual collision detection step is necessary because not all collisions are a result of the character's movement. Some collisions can happen when another collider moves against a stationary character, in which case sweep tests are of no use to us. It would serve a very similar purpose to the "enableOverlapRecovery" option that was added to the default CharacterController component recently. Sweep tests are also unreliable if we are already colliding with a surface, and moving against that surface. All this will allow us to remain in full control of how our character is affected by external forces/collisions, and how it affects other rigidbodies

    Here is the feedback page to vote on the issue: https://feedback.unity3d.com/suggestions/expose-more-of-the-physx-api-namely-penetration-depth


    We need a way to detect collision hits manually so that we can use it on Update(), instead of FixedUpdate() / OnCollisionStay(), etc...

    Here is why I think this would be important:
    I am working on a custom character controller, and I want it to be as perfect as possible. I think a CC that feels perfectly fluid and responsive is key to a game's success (depending on the type of game, of course). Due to the way Unity works, character movement typically has to be done in FixedUpdate(), because that's when collisions are processed.

    Now consider the following:

    • Update() happens before every drawn frame
    • FixedUpdate() and OnCollisionX() happen at fixed time intervals
    Conclusion: You cannot guarantee that you will collect collision hit information before every frame that is drawn. Therefore, you cannot process your character movement logic / ground detection before every frame. This results in undesirable choppy movement. It is hard to notice at first, but compare an object moving in Update() and one moving in FixedUpdate() at high FPS and you will easily notice it. There will be times when two Updates() happen in succession without a FixedUpdate() in-between, and when that happens, there will be a frame where the character will not have moved.

    Here's the console output of a simple test I made to confirm this :


    In this test, an object moves on FixedUpdate(). FixedUpdate Debug.Logs itself in the console, and so does Update (with the position difference since last update). You can clearly see that on most frames, the character doesn't actually move, because the FPS is higher than the FixedUpdate rate.

    Failed solution attempts:
    Here are the attempts I have made to try and detect collision hits on Update and/or mimmic a controller that runs on Update():
    • A disgusting bunch of Raycast() all around my character: Just kidding, I will never fall that low!
    • CapsuleCast(): This only works in the direction it is cast, so I'd need to do maybe 6-10 of these casts per frame in all directions, which is ugly, inefficient and unreliable.
    • OverlapSphere(), or even the hypothetical OverlapCapsule(): These return only the hit Collider, but not the contact point or normal of the collision. To use these functions, I would have to write my own collision detection code between my character's capsule and every other collider type in Unity, including mesh colliders. This doesn't seem like a good time, and it is the kind of functionnality that you'd expect to be already implemented in an engine. A very brave and determined individual actually went through the trouble of doing this, but this solution can only check spheres, and requires manual mesh collider preparation: https://roystanross.wordpress.com/2015/06/29/custom-character-controller-in-unity-release-2-0-0/
    • Detecting environment hits with OnCollisionEnter/Stay, but moving on Update: This creates a weird desync between movement and collision detection that results in a few frames of going through things when landing on the ground and ramming into a wall for example. Not very ideal.
    • Setting the fixedDeltaTime to 144hz: This solution guarantees that your monitor will never be able to display frames faster than your character's movement is processed. It may sound like the perfect solution at first, but the unfortunate downside of it is that the physics simulation becomes more costly. I'm a huge fan of playing at 144 FPS, but I really don't need all the physics simulation in my game to run at such a high frequency. I only need my character controller to do that.
    • Using "Interpolate" on the rigidbody: This is very close to being a perfect solution, but interpolate works on the rigidbody's velocity. If you want your character to be kinematic like I do, moving it through velocity is not an option. It has to be moved directly with its position, and Interpolate doesn't work in that case. (Right now, to achieve the "kinematic" effect while still being able to detect collisions, I apply all position and rotation constraints on my rigidbody, and set kinematic to false). On top of that, this becomes a problem in cases where you want your character to "stick" to the ground when going up a slope and arriving at a plateau. You will see your character make a little 'jump' at the top of the slope if you use interpolation. This becomes very noticeable in first person.
    Bottom Line:
    I think Unity would benefit immensely from getting CheckSphereHits(), CheckCapsuleHits(), CheckBoxHits(), and CheckMeshHits() functions that return an array of Collision or ContactPoint. These functions would allow us to collect collision hit information before every drawn frame, and therefore make great character controllers, among many other things. Basically our character would become a kinematic capsule rigidbody whose movement and manual collision response would be processed on Update(), making the rest of the world collide with it normally, but giving us complete control on its movement.

    If anyone has some kind of solution to this, please share. I also invite you to correct me if I'm wrong about the inner workings of Update() and FixedUpdate()

    Here is the Unity Feedback post if you want to vote for it: https://feedback.unity3d.com/suggestions/additional-raycasting-slash-collision-functions

    Thanks
     
    Last edited: Nov 10, 2016
  2. Roni92pl

    Roni92pl

    Joined:
    Jun 2, 2015
    Posts:
    396
    TL; DR. Anyway do you know what interpolation is?
    Physics synchronization with rendering is big subject on it's own normally, and Unity do all this hard stuff for you - see rigidbody interpolation. If you don't move your character using rigidbody, then yes, you'll have to do movement every frame, not physx frame.
     
  3. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    As I mentioned in my big wall of text, I need my character controller to be completely unaffected by external forces, so I move my rigidbody's position directly instead of moving it through velocity (and all pos/rot constraints are active on the rigidbody). Interpolate does not work in that case. I would like to be able to process movement logic in Update(), but I have no way of gathering collision info on Update
     
    BrainSlugs83 and kegorov like this.
  4. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    Okay, here's an unrelated, simpler scenario that illustrates why I think this would be useful:

    Let's say I want to place an object in the world (think of a game like Rust where you can place furniture in a room).

    I'd use Raycast to find the point where I want to place my object, and I'd instantiate my object there. At this point, the object would probably be half-buried into the floor, walls and other props. So what I'd really like to be able to do is to call a "What am I currently overlapping with" function, that would give me an array of (point, normal, hit collider, overlapping distance). With that information, I would be able to resolve collisions manually to place my object properly and make sure it isn't colliding with anything.

    Using a Rigidbody.SweepTest instead of the initial Raycast wouldn't necessarily work, because it could return a hit that is between you and the surface you are pointing to. You'd need to do this in several iterations of Raycast and SweepTest in order to achieve the desired result, which is unfortunate when a simple collision detection function could save you all that trouble. Also, SweepTest doesn't give you control on which colliders you are sweeping with, as far as I know.
     
    Last edited: Jan 15, 2016
  5. Fu11English

    Fu11English

    Joined:
    Feb 27, 2012
    Posts:
    258
    But Unity would only have to do something similar themselves behind the scenes, no?

    An initial Raycast followed up by a RigidBody.SweepTestAll at the Raycast hit point would give you the desired information I should think, and is only a few lines of code.
     
  6. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    Unity would have access to whatever code PhysX is using to detect that two colliders are overlapping, so it wouldn't be just them using SweepTest behind the scenes (I don't want to pretend that I know exactly how Unity and PhysX work so this is of course all speculation).

    As for that, the SweepTest would only return the point, normal, and distance (zero) of the hit. Actually I don't even know if it would return a hit at all since they are already overlapping. Either way, it wouldn't tell you the information you need to resolve the collision. You'd know you want to push your object away from the hit normal, but by how much? SweepTest doesn't tell you the overlapping distance. This is easy to calculate if your collider is just a sphere, but with boxes, capsules, and especially meshes, it can get pretty scary
     
    Last edited: Jan 15, 2016
  7. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,459
    Interpolation doesn't use velocity. It is using past information by interpolating the Transform from the previous body position to the current body position. Extrapolation is predicting future information by extrapolating from the current body position to a possibly future position based upon the current velocity.
     
  8. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    When I said rigidbody interpolation used velocity, it was after doing the following test:
    • I set the targetFrameRate to 144 and the fixedDeltaTime to 15 (fps), so I have a high framerate but slow physics updates
    • I create a rigidbody cube with interpolation on
    • I make my cube move at a constant speed by setting its rigidbody.velocity directly
      • Result: very smooth movement
    • I make my cube move at the same constant speed through transform.position or even rigidbody.MovePosition() during FixedUpdate()
      • Result: choppy 15 FPS movement
    Is there something I missed?
     
    Last edited: Jan 16, 2016
    BrainSlugs83 likes this.
  9. Roni92pl

    Roni92pl

    Joined:
    Jun 2, 2015
    Posts:
    396
    Yes, FixedUpdate is invoked at physics rate(15hz in your case), as I said, you need to move it in Update loop, if you want it to be smooth ( invoked per frame). Interpolation doesn't affect how often FixedUpdate is called, so this behaviour is normal, and expected.
     
    sebsmax likes this.
  10. funshark

    funshark

    Joined:
    Mar 24, 2009
    Posts:
    225
    It seems you didn't really read what he wrote
     
    BrainSlugs83 likes this.
  11. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    First of all, the issue here is that it was said that rigidbody interpolation interpolated between positions without using velocity, and I don't understand how my test gave those results if that really is the case.

    Second of all, regardless of if interpolation works like that or not, having access to some sort of collision/overlap detection library would still be an absolutely crucial addition to Unity (a library that contains collision detection functions for any and all combinations of sphere, capsule, box, mesh). This would allow us to do stuff like I described in my "placing furniture in a room" example above. And it would allow me to, as you suggested, handle my character controller logic in Update(). Currently, it seems to be impossible to do that, unless I write that entire collision detection library myself.

    I would assume that this collision library I am talking about already exists within Unity, because it is able to fire OnCollisionX() events afterall. So in theory, all that would be left to do is exposing those functions to the user. If Unity is worried that people would misuse them, maybe put them in UnityEngine.Internal for example?
     
    Last edited: Jan 18, 2016
    BrainSlugs83 likes this.
  12. Iron-Warrior

    Iron-Warrior

    Joined:
    Nov 3, 2009
    Posts:
    838
    I read through the thread, and since I encountered a fair amount of similar issues, here's the answers I have from my experience:

    I haven't used the built in CC for a long time, but using a quick test it seems to work fine in Update. Is there any reason it can't be run in the Update method? The CC has it's own collision flags for outputting collision, too.

    CapsuleCast and SphereCast are also a bit unreliable, as they won't detect objects that are touching the initial volume that is the origin of the cast.

    As an authority on the above package: multiple spheres do work really well to approximate a capsule and aren't particularly inefficient provided the number of spheres is not too great. I ran into a ton of problems writing that controller, but one that I surprisingly never really encountered were errors due to collisions being "missed" in the gaps the spheres formed. As well, the mesh collider preparation is not manual in the sense that the user needs to do editing work on each mesh, but is an automated process that is applied after adding a script (unless that is what you mean by manual, if so my apologies!)

    Since there's been a bit of a discussion in this thread on how interpolation/extrapolation works with rigidbodies, I did my own test using the code below:

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class Movement : MonoBehaviour {
    6.  
    7.     enum MoveMove { Force, FixedUpdateManual, UpdateManual, Controller }
    8.  
    9.     [SerializeField]
    10.     MoveMove moveMode;
    11.  
    12.     [SerializeField]
    13.     Vector3 velocity;
    14.  
    15.     void Start()
    16.     {
    17.         if (moveMode == MoveMove.Force)
    18.             GetComponent<Rigidbody>().AddForce(velocity, ForceMode.Impulse);
    19.     }
    20.  
    21.     void FixedUpdate ()
    22.     {
    23.         if (moveMode == MoveMove.FixedUpdateManual)
    24.             GetComponent<Rigidbody>().MovePosition(GetComponent<Rigidbody>().position + velocity * Time.deltaTime);
    25.     }
    26.  
    27.     void Update()
    28.     {
    29.         if (moveMode == MoveMove.UpdateManual)
    30.             transform.position += velocity * Time.deltaTime;
    31.  
    32.         if (moveMode == MoveMove.Controller)
    33.             GetComponent<CharacterController>().Move(velocity * Time.deltaTime);
    34.     }
    35. }
    36.  
    And got this:



    With a fixed timestep of 0.25. Green is being moved by an initial impulse, yellow manually in Update, and blue in FixedUpdate with Rigidbody.MovePosition. (Bear in mine my gif recorder works at 33 FPS, so the top two look a bit jittery, but they are smooth in Unity). All are non-kinematic and have interpolation enabled.

    Returning Collisions or ContactPoints is a bit more complex than it seems at first. If you're doing something like OverlapSphere:



    These two spheres are obviously intersecting, but where are the collision points? We could draw a ring around the spheres where the two intersect, but that's not really a "point" of collision. A physics system has access to the velocity of the objects and can, with some accuracy, determine where these two objects hit each other. This is kind of a tangent but I felt it was useful information in this thread.

    Anyways, I definitely would really love a much more extensive series of Physics methods. Apparently we did get OverlapBox and BoxCast in 5.3 (I'm on 5.2), but it would be great to get an entire suite: OverlapCapsule, OverlapMesh, dare I even say...OverlapCylinder?!? There are lots of times when you need to be able to detect these kind of intersections at will, and a custom character controller is just one example.

    In addition, having access to some more low level methods would be really useful too. So far we get Collider.ClosestPointOnBounds, but it would be awesome to have methods that give us the closest point on any collider with respect to another point, since these methods are fundamental to building custom collisions.

    Games that are lauded for having tight player controls tend to have extremely fine control over their character's physics, and for some applications that can be bit tough to achieve given that your options are to either use the limited built in CC, or a very clumsy rigidbody controller. Great post overall, good to see this discussion opened from time to time.
     
    Last edited: Jan 19, 2016
    Raptosauru5 likes this.
  13. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    You're right, I see your point. The thing is, as you most likely already know, when we're not dealing with a sphere, it's not very simple to figure out what that "other point" is. Especially not with a mesh collider. So I guess what we would need in this collision library is:
    • OverlapBox/Sphere/Capsule/Mesh(), which returns the overlapped Colliders
    • ClosestPointsOnColliders(Collider colliderA, Collider colliderB, out Vector3 pointOnA, out Vector3 pointOnB, out bool intersect), which outputs the closest point on A's surface to B, and the corresponding closest point on B's surface. And also if the two colliders intersect
    • DistanceBetweenPoint/Segment/Plane, etc... always nice to have
    So in the case of a capsule-based character controller, our collision resolution would work a bit like this:

    Code (CSharp):
    1.  
    2. void Update()
    3. {
    4.     // for each Collider in our OverlapCapsule()
    5.     //      ... Vector3 pointA, pointB;
    6.     //      ... bool intersect;
    7.     //
    8.     //      ... ClosestPointsOnColliders(ourCapsule, theOverlappedCollider, out pointA, out pointB, out intersect)
    9.     //      ... if(intersect)
    10.     //          ... ourCharacterTransform.position += (pointA - pointB);
    11. }
    ... something like that, I think. I kinda have doubts about whether or not ClosestPointsOnColliders would give us what we need to know and work correctly for any collider type.



    According to my MS Paint algorithms, if the two selected surface points are the ones that are the furthest away from each-other's surfaces but inside each-other's bounds (in the case of an intersection), I thiiiiiiiink it would work? Dunno about the performance implications of that, though. I'm also starting to ask myself if PhysX (and physics engines in general) maybe only detect collisions through sweeps instead of overlaps, which would explain why we don't have such functions available. After reading a little bit about it, it sure sounds like it.

    ________________________________________________________

    P.S:
    In your SuperCharacterController, even if you never had any problems with stuff going through the gaps between your character spheres, I wonder if you could get a perfect capsule shape with three spheres if the center sphere is big enough so that the radiuses of its upper and lower "slices" (green lines) equals that of the upper and lower spheres? And then, for this center sphere, you just filter out all "closest points" of overlapped colliders whose shortest distance from the capsule's segment is greater than your capsule's radius (see red areas in picture)? Maybe it's just not worth it, too.
     
    Last edited: Jan 28, 2016
  14. Iron-Warrior

    Iron-Warrior

    Joined:
    Nov 3, 2009
    Posts:
    838
    You're correct in that it's just not a one size fits all. The simple ClosestPoint test works great for Spheres against anything, but for different volumes different tests are required. For something like Capsule-Box intersection, for example, one of the main goals is to find the distance between the inner segment of the capsule from the box, which gets you the closest point on the surface of the box with respect to the line segment (as opposed to with respect to a point).


    This also gives us the displacement vector to push the capsule out. What I'm getting at here is that typically when you do an intersection test, you're also supplied with data that is useful to finding a displacement vector and pushing the object out. So ideally, Unity's OverlapX methods would output some sort of CollisionData struct that would supply all of the data that was retrieved while running the intersection test (as well, it would also be really nice to have the above methods you wrote too).

    ________________________________________________________

    I've thought about sitting down and doing something like this. Your way would work really well, and another way to do with would just be to use and OverlapSphere large enough to envelop the entire "Capsule" to retrieve all objects that "may" be touching you, and then run a capsule intersection against all those objects to cull away ones that aren't touching the capsule. This of course would require you to write a bunch of custom Capsule-X intersection tests, and since I never had any issues myself I never got around to it. But it would be really cool to have, since you never know what kind of wonky geometry you might encounter.
     
  15. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    I just wanna say... Nvidia PhysX, which Unity uses, explains on their website why rigidbody character controllers are a terrible idea and don't feel great
    http://docs.nvidia.com/gameworks/co...ntrollers.html#kinematic-character-controller

    And when you consider the fact that Unity's built-in CharacterController component only provides us with a collision callback when the collision is the result of character movement (resulting in this kind of problem), we are left with an engine that cannot do good character controllers!

    Unity, can we get a comment on this? I've heard somewhere that 5.4 introduces a "Recovery mode" for the CharacterController. What does it do? Is this our salvation?
     
    Last edited: Feb 11, 2016
  16. vladibo

    vladibo

    Joined:
    Jan 29, 2013
    Posts:
    38
    What about the good old DIY?

    https://github.com/vbodurov/unity-functions

    Here is my project with different collision algorithms and visualizations, like:
    capsule - capsule
    ray - triangle
    triangle - line
    triangle - triangle
    triangle - wheel
    and other
     
  17. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    I thought about doing something like this at some point, but I ended up deciding against it because this most likely wouldn't play nice with the rest of Unity's physics engine. I need a characterController that can properly interact with other physics objects, such as having physics chains connected to it or dragging other rigidbodies. Maybe I could've ended up finding a way to make it all work if I wrote an entire physics engine from scratch (collision detection, ridigbodies, physics constraints, cloth, etc...) all by myself and replace Unity's PhysX completely, but I simply can't see this being worth it. It would take a very substantial amount of work to make all this, AND make it all safe and optimized. I just don't have the time for it. And it's the kind of thing where not too long after I'm finished with it, either Unity will already have improved its own physics engine to allow more flexibility, or a new, better engine will have come along

    But anyway, concerning the whole CharacterControllers thing, I found two main ways to make this work with the current physics engine:
    1. If your game can afford it (in other words, if there's not too much physics going on), let the user select their target framerate (60 or 144), and set both the fixed update rate and the target framerate to that. So you know the physics update will always be higher or equal to the display framerate. This is by far the easiest solution, but its disadvantage is that your physics simulation will become much costlier at 144fps. I know UE4 by default doesn't have a fixed deltaTime for physics, and it runs the physics sim at every regular frame (it makes things not as stable as in Unity, but the benefit is in the smoothness and repsonsiveness of the simulation). So basically this would be the equivalent of that in Unity, except without an unlocked framerate
    2. Rigidbody interpolation. I said in my first post that there were problems with this, but I was wrong. Interpolation for character controllers can work if:
      1. You don't apply and positional constraints on the rigidbody (constraining rotation x and z seems to be fine, though)
      2. You handle all character movement through AddForce or setting Rigidbody.velocity directly
      3. You handle all character rotation through AddTorque or setting Rigidbody.angularVelocity directly
      4. You have complete control on its velocity at all times, and don't let any external forces affect it normally. Always explicitely set what the velocity is at each FixedUpdate(). Your input needs to have complete authority over the velocity of the rigidbody. This will give your character the "kinematic" feel
    Not following rules 1,2,3 will break your interpolation. So any direct modification of Transform.posiiton/rotation won't do. Rigidbody.MovePosition/Rotation is also not an option.
    An alternative that I haven't explored yet is making my own interpolation function, so that I can have full control over it. Now that I think about it, it would probably be the best option. I'd need to make one anyway for networking compatibility

    I'd also like to point out that two new extremely useful features were released since I started this thread:
    • CharacterController.enableOverlapRecovery: This basically fixes Unity's CharacterController component, and makes it a great choice for making your own character controllers. Works like a charm. I have yet to see if the CharacterController's GC alloc problems have been fixed, though
    • ContactPoint.separation: This allows you to handle your own collisions. Make a rigidbody object with all constraints applied, and you can solve the collisions manually in OnCollisionEnter using the contact normal and separation

    Final note: I also want to look into this: https://www.assetstore.unity3d.com/en/#!/content/62991
    Looks very promising, and it would give me all the freedom I need. I'm just a little bit worried about any GC issues, which seem to be very common among Asset Store packages
     
    Last edited: Aug 22, 2016
    Ultroman likes this.
  18. EnokV

    EnokV

    Joined:
    Apr 14, 2016
    Posts:
    56
    Bumping because I still think this is relevant.

    From: http://docs.nvidia.com/gameworks/content/gameworkslibrary/physx/guide/Manual/GeometryQueries.html

    Section: Penetration depth

    Is this exposed in Unity? I've looked through the scripting API but I haven't found anything similar to this.

    I might ofcourse be wrong but it looks to me like we could have something like:

    Code (CSharp):
    1.  
    2. Vector3 direction;
    3. float depth;
    4. if(ComputePenetration(out direction, out depth, primitiveColliderGeometry1, transform1, primitiveColliderGeometry2, transform2)){
    5.  
    6. transform.Translate(direction * depth);
    7. }
    8.  
    which should if I understand the docs correctly, push us away from geometry

    getting the hit point should be as simple as casting a ray in the negative direction after you have been separated from the object, no?

    Educate me if I'm wrong here, I'm pretty inept at these kinds of things(gamedev) but to me this sounds like exactly what we need.
     
  19. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
  20. EnokV

    EnokV

    Joined:
    Apr 14, 2016
    Posts:
    56
    Yes, but ContactPoint is a part of the Collision struct of which an instance is only sent to OnCollisionEnter/Stay/Exit which in turn is only called if you use a Rigidbody that is non-kinematic or a CharacterController.

    What I mean is that the function showed in the PhysX API should be exposed as it is. E.g. bool Physics.CheckPenetration(out Vector3 direction, float depth, geom, geomPos, geom2, geomPos2)

    This would allow you to check if 2 collider geometries are intersecting eachother and it would also calculate the correct values for you to use in a translation in order to separate them from eachother, without the need of a rigidbody or the stock character controller.

    As I mentioned above, a raycast could(theoretically?) be used to get the contact point as rays can hit colliders without rigidbodies.

    What this gives you is the ability to do a capsule/sphere/box overlap to get all colliders, which you loop through and then you just check if your custom character controllers collider geometry intersercts any of these, in which case the correct values are spoonfed to you to perform a translation.

    I mean, yeah I can use a rigidbody and I have that ContactPoint separation thing, sure. But what use is it? My rigidbody cannot be kinematic so it will still resolve collisions on its own. The only thing that'd happen(I think, haven't tested) is that I perform my own collision check on top of an existing one, effectively overriding the result(if I just zero out velocity every frame or w/e). To me this smells a lot, it feels like a very hacky way of doing it.

    EDIT: I posted a feedback on it explaining more in detail what this would bring to unity.
    https://feedback.unity3d.com/suggestions/expose-more-of-the-physx-api-namely-penetration-depth
     
    Last edited: Nov 4, 2016
  21. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    Yeah you're right. Having access to that method would be a game changer .

    However, I've discovered something pretty interesting not even a week ago: kinematic rigidbodies CAN recieve collision events!, and can be interpolated smoothly using MovePosition and MoveRotation. Kinematic Rigidbodies will recieve collisions if they are colliding with other non-kinematic rigidbodies (see the collision matrixes at the bottom of this page: https://docs.unity3d.com/Manual/CollidersOverview.html ). So hypothetically, you could make a game where you have a kinematic character controller and a level consisting of rigidbody colliders with all constraints on, so they don't move. And collision between kinematic characters could be done through rigidbody.seeptest or capsulecasts

    My only fear with this is performance. I'd have to do some profiling to see how much of a performance difference there is between 1000 constrained rigidbodies and 1000 static colliders. I also want to test the difference between 1000 individual constrained rigidbody colliders, and 1 constrained rigidbody with 1000 normal colliders under it (to see if it affects PhysX's broadphase). Finally, I need to test if those rigidbodies can be static and still work. If we could have a Unity dev's opinion on this, that'd be great
     
    Last edited: Nov 4, 2016
  22. EnokV

    EnokV

    Joined:
    Apr 14, 2016
    Posts:
    56
    Yeah, this I knew from before but I don't see it as a viable option mainly because it's still quite a hack. The only thing I can suggest is to battle Unity about this and show that this is indeed a MUST HAVE functionality. At the very least allow us to write our own custom components on a lower level directly accessing parts of the PhysX API(I assume this is how they are written).
     
  23. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    So I just made those tests. I made a scene with a "floor" composed of 2500 box colliders, and a script that instantiates 100 rigidbody boxes that fall on that floor. I tested with six different types of "floor" colliders.



    These are the results, measured in the time of the total frame where fixedUpdates happened (just to be sure everything was taken into account):
    Constrained rigidbodies: average 5ms per frame
    Standard colliders: average 4ms per frame
    Constrained static rigidbodies: average 4.2ms per frame
    Standard static colliders: average 3.7ms per frame
    Standard colliders under a single constrained rigidbody: collision detection breaks / is unreliable
    Standard static colliders under a single constrained static rigidbody: collision detection breaks / is unreliable

    So there is a difference in performance, but it is extremely minimal. Seems like this would be a valid option to consider.

    EDIT: Ah... but you might run into trouble if you need moving platforms. They would need to be kinematic and not have any constraints.... right now I don't see a way to make it work aside from special-case CapsuleCasts. You're right, this is starting to feel hacky. I'm gonna put your link at the top of the thread
     
    Last edited: Nov 4, 2016
  24. EnokV

    EnokV

    Joined:
    Apr 14, 2016
    Posts:
    56
    Neat, hopefully it'll get some recognition!

    In the meantime I'll just stick to 2D prototyping with raycasts.

    EDIT: I'm reading about ContactPoint.separation more carefully now and it doesn't seem to do what is described in the PhysX doc I linked.

    E.g. it doesn't contain the intersection depth or in what direction translation should be made in order to separate objects. Ofc I might misinterpret what it says, but looking at the docs you can see that the function returns a bool and also a direction and a depth.

    ContactPoint.separation seems to contain only the distance between colliders at the event of a collision, which means this is set after a collision has occured.

    The function described in the PhysX API seems to run an algorithm on the actual collision geometry to check if they intersect, then it calculates the values you need in order to separate the 2.

    In short, it would be meaningless for the method to return a "collision" because a collision only happens with rigidbodies and character controllers. I think.

    EDIT2: I realize I have been a bit vague so I'll drop this paint explanation. Notice how I changed to Mathf instead since it would make more sense to have this method reside in that class instead.

    Hopefully this will clear out confusion.

     
    Last edited: Nov 4, 2016
  25. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    basically, you would use it like this:
    Code (CSharp):
    1.  
    2.     // Resolve collisions manually
    3.     void OnCollisionStay(Collision coll)
    4.     {
    5.         foreach (ContactPoint contact in coll.contacts)
    6.         {
    7.             this.rigidbody.position += (contact.normal * -contact.separation);
    8.         }
    9.     }
    (it's actually a little more complicated than that because you have to compute the total displacement of all contacts and THEN apply the rigidbody position, but this is just so you get the idea)

    If your rigidbody is kinematic, the collision will never resolve itself, so you're free to resolve it manually

    But yeah.... now I realize kinematic rigidbodies are currently too limited for this to work well (all level collisions need to be constrained rigidbodies, cant do moving platforms, etc....)

    EDIT: contact.normal gives you the "direction", and contact.separation gives you the "penetration" in your drawing. So I think you'd have all you need, were it not for the problem that you're dependant on OnCollisionStay
     
    Last edited: Nov 4, 2016
  26. EnokV

    EnokV

    Joined:
    Apr 14, 2016
    Posts:
    56
    The idea I had in mind with this method exposed would be something like.


    Code (CSharp):
    1.  
    2.     void Update ()
    3.     {
    4.         foreach(Collider col in Physics.OverlapCapsule()) {
    5.             Vector3 direction;
    6.             float depth;
    7.  
    8.             if(Mathf.CheckPrimitivePenetration(playerCollider, col, playerCollider.transform.position, col.transform.position, out direction, out depth)) {
    9.                 transform.Translate(direction * depth); //Move away from the other collide just enough to lick the surface of it
    10.  
    11.                 //Perform a raycast in -direction to get the point of collision
    12.                 //Store collision data in your own collision struct
    13.             }
    14.         }
    15.     }
    16.  
    EDIT:
    Ah yes, I forgot about the normal but this still boils down to the fact that the values providied by ContactPoint.separation and .normal still are useless in the sense that if you use them to push yourself away from geometry, it's gonna be quite useless because the physics engine has already determined that a collision has in fact happened and what you'd be doing is apply your own "collision" on top of that.

    This is why it makes little sense for the function shown in the PhysX doc to return a collision as this suggests a collision has already occured, which is not what we(I?) want because we(I??) don't want to use rigidbodies.
     
    Last edited: Nov 4, 2016
  27. EnokV

    EnokV

    Joined:
    Apr 14, 2016
    Posts:
    56
    *bump*

    Can we get a Unity employee to comment on this?
     
  28. yant

    yant

    Unity Technologies

    Joined:
    Jul 24, 2013
    Posts:
    596
    Hi everyone,

    I've just been shown this thread, thanks for all the feedback. Seems we have actually exposed a few things being talked over here (some devs been asking for them in my twitter). Leaving the multiple questions asked alone, as far as I could understand, the thread boils down to the request of exposing PxGeometryQuery::computePenetration / PxComputeMeshPenetration. Is that a correct perspective? If yes, I could just that plan to do that with the first occasion.

    Anthony
     
    PowerJake, HiddenMonk, EnokV and 2 others like this.
  29. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    Yes! These methods are all we need (and ideally they would have zero GC alloc).

    It would also have to work with kinematic rigidbody colliders and static non-rigidbody colliders. I'm not sure if this method would take into consideration the rigidbody type at all, but I'm saying that just in case.... because I know kinematic rigidbodies currently cannot detect collisions with static colliders and other kinematic rigidbodies.

    I've added an example use case in bold text in the thread's initial post, if it can be useful to you.

    Thank you so much!
     
    Last edited: Nov 10, 2016
  30. Iron-Warrior

    Iron-Warrior

    Joined:
    Nov 3, 2009
    Posts:
    838
    Expose them all Yant! Expose them alllllllllllllllllllll!
     
    Raptosauru5 likes this.
  31. EnokV

    EnokV

    Joined:
    Apr 14, 2016
    Posts:
    56
    @PhilSA This method takes into account the collider geometries you feed into it, then it determines if they overlap and calculates the correct numbers in order to separate them. It doesn't matter if there's a rigidbody involved or not, if I read the docs correctly.

    @yant That's great to hear! We've been in dire need of this functionality for far too long.
     
  32. yant

    yant

    Unity Technologies

    Joined:
    Jul 24, 2013
    Posts:
    596
    Just a quick question: would it make sense to expose functions accepting primitives instead of colliders? I'm guessing there might be a lot of use for those where devs want to have implicit shapes instead of having to maintain the cost of collider. Probably not relevant to this particular discussion about character controllers since you'd still want to have a collider that you move yourself just for the purpose of the surrounding objects having a chance to react somehow.
     
    EnokV and HiddenMonk like this.
  33. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    Absolutely. The more versatile/efficient, the better
     
    Last edited: Nov 21, 2016
  34. Iron-Warrior

    Iron-Warrior

    Joined:
    Nov 3, 2009
    Posts:
    838
    In a perfect world it would be awesome to be able to implement ISupportMappable (or whatever it's called in PhysX) to allow us to define whatever convex shape we wanted...heck this could even be used to allow the extension of the Collider class. When in doubt, expose everything!
     
  35. EnokV

    EnokV

    Joined:
    Apr 14, 2016
    Posts:
    56
    @yant What @PhilSA and @Iron-Warrior said - the more playground everyone has, the more epic content we can produce with less hassle.
     
  36. yant

    yant

    Unity Technologies

    Joined:
    Jul 24, 2013
    Posts:
    596
    This is actually pretty hard to implement right. Any calls from the native code to managed cost lots. Garbage collection. Tricky to protect data while executing callbacks (e.g. destroying stuff in a weird way while inside a callback; right, we disallow destruction -- but deactivations are still possible and are effectively the same thing internally). Script calls don't multithread nicely on top of that.
     
  37. EnokV

    EnokV

    Joined:
    Apr 14, 2016
    Posts:
    56
    By the way - I interpret this as you have put the implementation in your TODO, or that you're working on an implementation already?

    If so, what's your expected ETA? Is this something we could be seeing in 5.6 or even earlier? Is it worth halting the implementation of a workaround(custom collision geometries) and just focus on other aspects of my project?
     
  38. yant

    yant

    Unity Technologies

    Joined:
    Jul 24, 2013
    Posts:
    596
    Yes, you're interpreting it the right way. On the other hand, I won't be able to estimate when it's ready, unfortunately. Expecting it in 5.6 seems like a fair guess. Not 5.4 or 5.5, definitely.
     
    EnokV and PhilSA like this.
  39. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    I have spent a stupid amount of time working on custom collision detection for capsules, but even with what I have now, the performance is terrible compared to what I think physx could give.
    Having a way to do collision detection without rigidbodies so we can use it in Update instead of FixedUpdate is a must (as well as no garbage collection).
    I am getting very excited seeing you are working on this =).
     
  40. EnokV

    EnokV

    Joined:
    Apr 14, 2016
    Posts:
    56
    @yant TIL: There's apparently some kind of penalty if you move an object with a collider that has no attached rigidbody(kinematic or not) since the collider is then considered static and has to rebake collision meshes every frame? Is this correct? The unity docs on colliders also highly suggest to always have a rigidbody attached to any moving object with a collider - what's the deal with that?

    Wouldn't it make sense to be able to mark a collider as non-static yourself in the inspector should you not want to use a rigidbody at all?

    Considering the whole idea with PxGeometryQuery::computePenetration would be to resolve your own collision and thus not have to rely on a rigidbody for anything at all.

    That said, I haven't encountered this said penalty at all but others apparently have. My scenes aren't very advanced yet though.

    How tightly coupled are rigidbodies and colliders?
     
  41. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    The issue with moving colliders without a rigidbody has apparently been fixed since unity 5 and is explained in this blog by unity.
    Look under "Moving Static Colliders"
    https://blogs.unity3d.com/2014/07/08/high-performance-physics-in-unity-5/
     
    EnokV likes this.
  42. EnokV

    EnokV

    Joined:
    Apr 14, 2016
    Posts:
    56
    HiddenMonk likes this.
  43. yant

    yant

    Unity Technologies

    Joined:
    Jul 24, 2013
    Posts:
    596
    I'm glad that older post of mine still serves some need. :)

    Just wanted to add that it's advisable to have a kinematic rigidbody attached to a collider that you want to move from code even though there's no longer that huge perf penalty as it was in pre Unity 5.x. The reasons being:

    - Certain parts of PhysX would assume that the static object doesn't move and won't check if it's still there or not. Example: a WheelCollider-based vehicle once asleep, won't be woken up by removing a static ground underneath. About the same holds about a Rigidbody sleeping on top of a static object that is being moved around. The difference is that it may still pick up the moved static in case their AABBs no longer overlap.

    - It's important to have objects connected with joints moved by ::MovePosition / ::MoveRotation. Otherwise, PhysX treats the movement as a kind of unphysical teleport with joints experiencing over-stretch or explosions as a result. Using the above mentioned functions ensures that there is an actual implicit velocity vector computed during the simulation and this velocity is passed down the pipeline to the joints solver code.

    - Other misc considerations.

    A
     
    cstlmode and HiddenMonk like this.
  44. Bezzy

    Bezzy

    Joined:
    Apr 1, 2009
    Posts:
    75
    Oh! I'm glad I've found this thread! I'm in the right place, struggling with all the same issues you all have. Solidarity!

    I'm using the same BSPTree script that super character collider uses to resolve penetration, because no matter how hard I tried, swept collisions would suffer from floating point issues which allowed tiny incremental movements to take you inside a wall - especially on long triangles. I.e. running near parallel to a very long wall would result in this weird floating point sweet spot where the sweep did not the wall, but when you place yourself to the end of the sweep, the next sweep from that position counted as starting inside the wall - so you started to fall through it.

    I do a capsule check any time I reposition myself due to a sweep test, and if it finds anything, I use a dictionary<meshcollider,bsptree> lookup to find the closest point to the bottom of the capsulse and push away from that by a radius' worth, for each mesh being touched (unless all the directions resolve to zero, i.e stuck between opposite sides of a corridor, in which case, i need to do some kind of slide response, or just stop you dead). Also have a host of "find closest point on" calls on primitive types, but i threw them together last week and they may not be perfect.

    The results are pretty damn solid, but my code is currently a pretty big mess of extra data for traces to check and double check things. Hopefully I get a chance to start from scratch with my learnings, and turn it into something that I could possibly share onward.

    Oh, and I actually don't use a collider at all. Just capsule sweeps and capsual overlap checks. I put collider children on stuff for their various purposes (pushing other physics objects around, or getting detected by trigger zones) but not for movement.

    And although I have a rigidbody, I do not bother with trying to keep stuff working in fixed update + interpolate. I tried hard to do it what I thought was "the correct way": in fixed update, since physics will only actually respond in line with that fixed frequency. Turns out, It's a huge ball ache work around to make the thing move smoothly since mouse update polls at render update rate (as it should). for a first person game, it's just garbage game feel to put it in fixedupdate while the camera's in render update. I tried my own interpolation, but it turned out, at that point, that i might as well move the player movement updates to the same timings as input. Glad I did. Haven't looked back. Have to make concessions for any rigidbody interactions that happen, but that's fine.

    I also try to do a quite fake thing where I resolve the downward standing trace to how a cylinder would respond to that contact. That part is a bit herky jerky and wrong, but I just hate the feel of "slipping" off a ledge due to a round bottom rather than the boolean feel of being on/off a ledge.

    But yeah. A very cool, faster-than-we-can-accomplish-in-script "closest point on collider" call would be absolutely amazing for unity to build in.
     
    Last edited: Dec 4, 2016
  45. yant

    yant

    Unity Technologies

    Joined:
    Jul 24, 2013
    Posts:
    596
    Yeah, I feel the pain.

    We've updated PhysX in Unity 5.5 to a version where they have addressed (hopefully all of) accuracy issues with the physics queries against the scaled objects. I do remember closing multiple cases where a SphereCast failed to detect the correct hit against meshes. Could you check it out and let me know the result? Thanks.

    As for the closest point on something, this also gets exposed real soon. It's probably not a good practice to refer to the Twitter posts from here, but I've actually tweeted a relevant gif over there: https://twitter.com/AnthonyYakovlev/status/804657788953698304

    One extra note, is that in Unity 4 and earlier one couldn't really rely on the physics queries returning the correct results unless there was a fixed-update in between the last collider's pose change and the query. With PhysX 3, this was lifted in fact, but wasn't reflected in our docs for a while. Just to clarify: since Unity 5.0 you don't have to wait anything after a collider's pose was changed. All the physics queries are capable of picking up the change with no extra hassle as they use the 'dirty' flags internally and update all the spatial structures at the time of the call.
     
    EnokV, HiddenMonk and PhilSA like this.
  46. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    Christmas miracles ARE real!
     
    Last edited: Dec 5, 2016
    LouisHong and jepidoptera like this.
  47. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
    Is there any chance of having this also be true for objects who's pose are changed because they're destroyed?

    With ComputePenetration and ClosestPoint in, the only really big akwardness of Unity's physics is that raycasts and other queries still hit objects that have been Destroyed() on the same frame, since destruction doesn't kick in until end of frame. Since there's also no way to check if a thing has been queued for destruction, the only way to resolve a situation like that is to either move the object to another layer as it gets destroyed, or maintain a manual register of "objects destroyed this frame that should be ignored".
     
  48. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    I wonder if deactivating the rigidbody/collider on Destroy would do the job(?) It's possible that this isn't done automatically because it would incur a certain extra cost that you don't necessary need to have (i.e. checking for a rigidbody whenever an object is destroyed)
     
    Last edited: Dec 5, 2016
  49. boxhallowed

    boxhallowed

    Joined:
    Mar 31, 2015
    Posts:
    513
    This would be AMAZING, considering most of the time I just want to translate the position instead of messing with physics.
     
  50. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
    If you mean OnDestroy(), then, no. That's also called end-of-frame. If you mean as I destroy the object, sure. That's probably the best work-around.