Fixing ghost collisions on a plane made of multiple Colliders? - unity3d

Basic Problem: Unity's physics engine produces weird collisions when a player is moving over a flat surface made of more than one Collider. The ghost collisions occur at the joints between Colliders, and express as two behaviors:
This seems to be a problem with physics engines in general, based on this talk by Bennett Foddy:
https://www.youtube.com/watch?v=NwPIoVW65pE&ab_channel=GDC
Game Specifics:
In my case, the player is moving through a procedurally generated wormhole, composed of Segment objects using a MeshCollider. The wormhole twists randomly through 3D space, while the width and height change dynamically. The player can strafe 360 degrees around the inside of the tunnel (direction of gravity is relative to position).
This makes the simpler solutions I've found impractical. Those include:
Using a single object instead of many
Placing redundant Colliders behind the joints
I've managed to flag these erroneous collisions in OnCollisionEnter(). This method on the PlayerController works fine to identify these erroneous collisions, and raise a flag.
private void OnCollisionEnter(Collision other)
{
if (other.gameObject.tag != "Tunnel"){return;}
// Bit mask for tunnel layer.
int tunnelLayerMask = 1 << 10;
// Get the direction from the nearest Segment's origin to the collision point.
Vector3 toCollision = other.contacts[0].point - nearestSegment.transform.position;
if (Physics.Raycast(nearestSegment.transform.position, toCollision, out RaycastHit hit, 100f, tunnelLayerMask))
{
// Flag the collision if the detected surface normal
// isn't equal to the collision normal.
if (other.contacts[0].normal != hit.normal) { colFidelityFlag = true; }
}
}
But I'm at a complete loss when it comes to gracefully resolving the issue.
Currently, I'm just caching the player's velocity each frame. If a collision is flagged, I overwrite the resulting velocity with the cached velocity from the previous frame. This works for most conditions: the player ghosts imperceptibly into the floor for a frame, and gets past the offending joint.
But under high enough velocities or interactions with obstacles inside the tunnel, it is possible for the player to be ejected through the floor, and into space. I don't want to limit the velocity of the player too much, since the feel of the game partially relies on high velocity and hard collisions.
Does anyone know of a better way to resolve these erroneous collisions?

This is called "ghost vertices", and happens if you have like 2 box colliders (or something equivalent) and they are connected to each other. You could try to join the colliders so that instead of 2 separate connected colliders you have a single one.
Here ghost vertices are explained in more detail: https://www.iforce2d.net/b2dtut/ghost-vertices

Related

Why does the object get stuck in the wall when repelled?

I made the endless movement of the object and its repulsion from the walls, but it does not always work correctly. At rounded corners (sometimes even at a straight wall), it just gets stuck and stops moving altogether, or moves slowly to the point where it stops moving. What can this be related to and how can it be fixed?
private void FixedUpdate() {
rb.velocity = direction * normalSpeed;
lastDirection = direction;
}
private void OnCollisionEnter2D(Collision2D collision) {
//Repulsion from objects.
direction = Vector3.Reflect(lastDirection.normalized, collision.GetContact(0).normal);
}
There is a small distance between the objects, but the circle seems to stick to the wall and moves with it until it collides with another collider:
Example
there are objects under the circle that also have colliders, but the collision between them is not considered, since they have the same layer (in the settings, I disabled the collision for objects on the same layer). What can be done to fix this error and what can it be related to?
The object in the general scale:
Example
I tried to increase the size of the wall collider, tried to change polygon collider to box collider, connect composite collider, changed the mechanics of the object movement (in these cases, the movement could work incorrectly), but the result was always the same - the jams (sticking to the wall) continued.
It is difficult to answer your question without having more information, but I can suggest if you are using physics to move your objects - utilize physic materials and remove code that changes direction manually in OnCollisionEnter. Using physic materials you can easily make your object bounce from colliders of your choice without losing velocity.

Unity 2D physics is not colliding when player moves fast

A 2D circle shaped player has the following code
Vector2 target = Camera.main.ScreenToWorldPoint(Input.mousePosition);
transform.position = target;
which sets the player's position to the mouse position, and when it collides with enemies they get destroyed (simple concept).
The problem is that the enemies do not recognize collision when player passes through them quickly so they are not destroyed. This problem frustrated me I don't know why collision doesn't work when an object passes through another object quickly .
Is there a solution? Or it is just UnityEngine Maximum Performance
Thanks in advance.
I recommend you to see this link.
It explains much about Collision in unity.It looks similar to your game also.
You could also calculate distance between two objects and when the
distance is equal to zero you may destroy that object too.
Note1: this destroys the object only when it is coinciding with another object.
Or by calculating the outer distance between two objects when it is
equal to zero you destroy that object.
Note2: this destroys the object when two objects are starting to collide.

How to calculate the length of platform/object in Unity 5?

I'm new to Unity and after watching and reading some tutorials I'm now trying to make a simple 2D platformer kind of game. In the said game both enemies and player can jump to different platforms and traverse it like the old SnowBros game.
The problem I'm facing is related to programming the enemy movement. In my game there would be several types of enemies but generally for now there are two types, one that can jump from the platform and one that only walks upto the length of the platform, wait for 1 second then flip and walk backwards; meaning they don't get off the platform. Now this is an issue I'm having trouble with. I can't seem to find a way to calculate the length of the underlying current platform. I thought of using the collider.bound.min.x and max.x to come around the problem but the issue is I can't seem to find a simple way to reach the current platform's collider without fetching the script and then going through it.
Since, there would be many platforms of many different sizes and each platform is made up of a prefab of other platforms, it just doesn't seem like a workable solution to use the platform script and then traverse through it.
You can use Physics2D.Raycast to "sense" for collisions on a Ray. Imagine the enemy putting their toe one step forward, feeling if there is still solid ground, and then deciding whether to stop.
void Update()
{
Vector2 newPosition = transform.position + velocity * Time.deltaTime;
Vector2 downwardDirection = Vector2.down; // you may have to replace this with your downward direction if you have a different one
RaycastHit2D hit = Physics2D.Raycast(newPosition, downwardDirection);
if (hit.collider != null)
{
// solid ground detected
transform.position = newPosition;
}
else
{
// no ground detected. Do something else...
}
}
You can and should define the Layers your Raycast is supposed to hit, so it can ignore the enemy itself and avoid self-collision.
Well, I hope that you have prefabs of platform and in those prefabs put colliders at start and at end. You can specify layers and tags so that only enemy can detect those colliders and then you can detect tags on collision from enemy script and make your operation.
First create layers by opening Edit -> Project Settings -> Tags and Layers. Create two Layers
Create layers for enemy and enemyColliders and Goto Edit -> Project Settings -> Physics2D. Set collision matrix as EnemyCollider will collider with enemy only.
And your prefab will be looks like,
I hope this would help you.

Unity 5.2 - Moving character bumps between 2D edge colliders

I'm creating a fast-paced, 2D side-scrolling game on Unity 5.2, building my terrain out of discrete "blocks", each with its own EdgeCollider2D component.
Having a problem where my character gets bumped upward as it crosses from one block to another (imagine driving your car over a speed bump on the road).
This doesn't happen all the time. Seems to be random, which is even more irritating, as it makes finding a solution more difficult.
I've tried all of the suggestions that I could find for similar questions on this site, including:
Using CircleCollider2D's on the character
making sure the terrain blocks and their corresponding colliders are perfectly aligned. The attached screenshot shows one of the intersections.
changing the "Min penetration for penalty" setting to the minimum allowed value (0.0001)
switching between discrete and continuous collision detection for the character's RigidBody2D
increasing the mass and gravity scale for the character's RigidBody2D
... to no avail.
Beyond building a single, massive terrain object with a single edge collider from start to finish (which I'm trying to avoid), I've run out of ideas. Anything else I'm missing? Is it just a Unity bug?
Help!
Try detect the collision and set the vertical velocity to zero.
void OnCollisionEnter2D(Collision2D col)
{
if (col.gameObject.name.StartsWith("block"))
rigidbody2d.velocity = new Vector2(rigidbody2d.velocity.x, 0);
}

Unity: Ball falls through object that is rotating around another object

Imagine you have a ball falling due to gravity. When it encounters a rotating "cube" object, then you would expect it to bounce off of the object. However, in my case if the cube is rotating fast, the ball goes through it, but if the cube is rotating slowly, the ball hits it and bounces away as expected.
I am using RotateAround() inside the Update() method to achieve the "cube" object's rotation. I tried setting the ball's collision detection to Discrete, Continuous, and Continuous Dynamic with no luck.
My goal is to make the ball bounce away no matter how fast the "cube" object is rotating around another object.
Is there something else I should look into?
Thanks!
You can try lowering the Fixed Timestep value under Edit > Project Settings > Time.
Be aware that this will affect the performance of the game as you're calculating physics more often.
Documentation: http://docs.unity3d.com/Manual/class-TimeManager.html
Also, I assume that you have box and sphere colliders as opposed to mesh colliders? The former are more efficient at detecting collisions.