We need a way to detect and resolve collision hits manually

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): Geometry Queries — NVIDIA PhysX SDK 3.4.0 Documentation (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():

  • Collect all nearby colliders using OverlapCapsule
  • Test penetration against each of these colliders with “computePenetration”
  • Manually resolve collisions using the computed penetration information of step 2
  • 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)
  • 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

Original post text (You dont need to read it)

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: Custom Character Controller in Unity: Release 2.0.0 | Roystan Ross
  • 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

4 Likes

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.

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

2 Likes

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.

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.

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

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.

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?

1 Like

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.

1 Like

It seems you didn’t really read what he wrote

1 Like

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?

1 Like

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:

using UnityEngine;
using System.Collections;

public class Movement : MonoBehaviour {

    enum MoveMove { Force, FixedUpdateManual, UpdateManual, Controller }

    [SerializeField]
    MoveMove moveMode;

    [SerializeField]
    Vector3 velocity;

    void Start()
    {
        if (moveMode == MoveMove.Force)
            GetComponent<Rigidbody>().AddForce(velocity, ForceMode.Impulse);
    }

    void FixedUpdate ()
    {
        if (moveMode == MoveMove.FixedUpdateManual)
            GetComponent<Rigidbody>().MovePosition(GetComponent<Rigidbody>().position + velocity * Time.deltaTime);
    }

    void Update()
    {
        if (moveMode == MoveMove.UpdateManual)
            transform.position += velocity * Time.deltaTime;

        if (moveMode == MoveMove.Controller)
            GetComponent<CharacterController>().Move(velocity * Time.deltaTime);
    }
}

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.

1 Like

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:

void Update()
{
    // for each Collider in our OverlapCapsule()
    //      ... Vector3 pointA, pointB;
    //      ... bool intersect;
    //
    //      ... ClosestPointsOnColliders(ourCapsule, theOverlappedCollider, out pointA, out pointB, out intersect)
    //      ... if(intersect)
    //          ... ourCharacterTransform.position += (pointA - pointB);
}

… 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.

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.

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/content/gameworkslibrary/physx/guide/Manual/CharacterControllers.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?

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

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:

  • 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

  • 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:

  • You don’t apply and positional constraints on the rigidbody (constraining rotation x and z seems to be fine, though)

  • You handle all character movement through AddForce or setting Rigidbody.velocity directly

  • You handle all character rotation through AddTorque or setting Rigidbody.angularVelocity directly

  • 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

1 Like

Bumping because I still think this is relevant.

From: Geometry Queries — NVIDIA PhysX SDK 3.4.0 Documentation

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:

Vector3 direction;
float depth;
if(ComputePenetration(out direction, out depth, primitiveColliderGeometry1, transform1, primitiveColliderGeometry2, transform2)){

transform.Translate(direction * depth);
}

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.

You’re in luck, because it has been exposed very recently. 5.3 I think
here: https://docs.unity3d.com/ScriptReference/ContactPoint-separation.html

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