- Home /
Negate a Single Collision
I've been digging through numerous questions regarding the default contact offsets for collisions and bouncing upon transferring between seamless, parallel colliders. However, reducing a safety buffer to be nearly nonexistent seems like a silly solution to a common problem, since it would only introduce other physics abnormalities.
Instead, I've started taking a look at whether the collisions occurring are reproducible on a regular basis. Well, they're not.
// C#
void OnCollisionEnter(Collision other)
{
Vector3 cNormal = other.contacts[0].normal;
Vector3 hNormal = cNormal;
RaycastHit hit;
Ray ray = new Ray(transform.position, other.contacts[0].point - transform.position);
if(other.collider.Raycast(ray, out hit, (other.contacts[0].point - transform.position).magnitude * 1.01f))
{
hNormal = hit.normal;
if(cNormal != hNormal)
{
Debug.Log("unequal: " + cNormal.ToString("F5") + " --- " + hNormal.ToString("F5"));
}
}
}
In summary, what I'm testing is this:
1) Get the normal of the collision upon transferring between colliders.
2) Get the normal of a raycast fired toward the location of the collision
3) Test whether the normals are the same. If they're not, then I hit the rounded corner safety net. Otherwise, they were the same and I would not have bounced when transferring between them.
The problem, however, lies with dealing with this issue once I've found it.
One option is to set the Rigidbody's current velocity vector to the previous frame's value, but that doesn't appear to actually prevent a bounce. As well, it would disrupt movement speed and result in the player being unable to change their velocity as clearly as they should.
Because the raycast won't guarantee a hit on the top side of the object with 100% certainty, it would be foolish to assume that I can simply rely on trying to reset my velocity based on a tangent to the collision.
Physics.IgnoreCollision(gameObject.GetComponent<Collider>(), other.collider);
doesn't change the resulting velocity from the current collision, so that hasn't helped anything.
Are there are reasonable means of preventing a collision from affecting velocity under these circumstances? Have I simply been taking the wrong approach in the first place? Any advice would be greatly appreciated!
Answer by alexisrabadan · Apr 11, 2016 at 10:25 PM
I encountered this same problem in a recent build, I assume that your circle is moving quite quickly which is likely causing the issue (a slow moving fps wouldn't run into this, only a fast moving racer).
The solution with the car came naturally with the use of a raycast suspension system, which means the car never really touched the road but simply hovered above it, looking like it was touching. So in your case, the circle could send out a raycast straight down every fixedupdate, and move the height to a point if it is below a certain threshold.
Otherwise, the most simple solution is to change the ground colliders into one collider (a procedurally generated collider perhaps?)
I agree with this as it would be the simplest way to approach an issue like this. If I were encountering a problem like this I would have my object never actually touching the ground and just floating above it. Shoot a ray down, get the hit.point, add 0.05 (or whatever value) to the y position and make the objects position new Vector3(hit.point.x, hit.point.y + 0.05f, hit.point.z)
As I dont know what type of game youre making or what exactly this issue applies to, its also possible to check the objects y position. Never let it raise above a certain height.
Out of curiosity... have you tried making the colliders overlap slightly?
Unfortunately, overlapping the colliders doesn't solve this problem. The "defaultContactOffset" basically creates a buffer region around the colliders where it becomes easier to predict collision with them, and where edges are smoothed slightly as well. These smoothed edges aim to prevent colliding with a corner and being guaranteed to hit only the top or only the side of the collider. Ins$$anonymous$$d, it causes the impact to be deflected at an angle to improve appearance of simulation under circumstances where the collision isn't along otherwise flat ground.
Incidently, my design also involves many cases of being flung into the air (and not automatically losing all control in response), so it's not reasonable to simply lock the player onto the ground, when intentional physics interactions are meant to be able to launch the player into the air.
That would be simple enough if I weren't so relying heavily on full physics interactivity. I already turned the maximum angular velocity up to 500 from the default of 7 (just over 1 rotation per second), then back down to 145 when I discovered that somewhere in the 150-160 range, the object visibly appears to spin the wrong direction (at 0.01x timescale). I believe it was still spinning in the correct direction as far as physics interactions were concerned, but visual issues were beginning to arise from that one.
Next, as much as I'd like to try combining colliders together, I'm using too-irregular of shapes that multiple convex colliders are a safer preventative measure for extreme velocity than a concave collider would be.
Additionally, my general approach also includes alternate gravity options (attracting towards points/objects or repelling away from them, among others), so there's not such a simple "certain threshold" in my case.
If I were making something a bit more straightforward, though, then this would've been great for me.
In the end, it looks like reducing the defaultContactOffset is turning out to be the best solution for me.
After strenuous interactivity testing, ignoring collisions at odd angles meant preventing moving objects from launching the player away too often, and it still never solved the problem of visible hiccups when hitting the "edges" of colliders.
After some high speed (300+ meter-per-second) collision accuracy tests, it looks like bringing down the collision offset (default 0.1, reduced to 0.0001... then reduced again to 0.0000001) has not resulted in any erroneous behavior so far, at least, so I may wind up sticking with it after all.
That said, I'm marking your answer as correct because it was definitely a very reasonable suggestion. Even though I wasn't able to make use of it in this case, this could very easily solve such a problem for others.
is it a problem at the end of fixed update to just offset the rigidbody's position to float slighty above the ground? You could find the relative y position for cases of nonuniform ground
Well, seeing how my main means of control involves changing the direction of gravity, any change in elevation will inherently result in a large potential speed increase due to a lack of friction.
Lifting off the ground would mean falling back down during the physics calculations, which simply wouldn't work well under these circumstances.
If I were specifically and purposefully controlling the character more directly (e.g. AddForce()), then this solution would have been extremely viable. However, I am intentionally maintaining a loose control scheme which demonstrates an even greater variance between being on the ground or in the air (no matter how little difference there is between them) because I'm letting the primary physics interactions be resolved by the built-in physics engine.