📜 ⬆️ ⬇️

Is Grounded in a 2D Platform: How to find out if a character is worth it?

I'll be brief. Fought over this task for a long time, therefore I decided to share the solution. Engine - Unity3D.

Formulation of the problem


There is a character, there are platforms. Of course, the character collider and rigbodody, all twelve. On the platforms, too, colliders. On the platforms - effectors, because the platforms should be solid only from above. That is, if the character fell on the platform, he stands on it. But if a character walks past a platform or jumps under it - he freely passes through it.

A character can jump only if he is standing on the platform. Need to know if we are worth it.

Conditions:
')
1) The shape of the platform is arbitrary.
2) The character can stand on the very edge of the platform.
3) Platforms may be inclined.
4) Platforms can move.

Popular solution and why it does not fit


In the standard example of an asset store, it is proposed to use additional gameobject under the character, throw raikas from gamer into gameobject and see if there is an intersection with the ground.

1) If we “walk by” or “jump on”, then the rakecast will completely catch the “ground”, although the character is not worth it.
2) Raikast works on a specific point, not on the area. So, if the platform is not exactly below the raikast point - for example, we are standing on the edge of the platform, or on a small pebble - the check will not notice it.

Decision


The solution can not be obtained logically, only by experiment. For it stems from the features of the physics of the engine. You need:
using System.Linq is generally a handy thing, I recommend reading it, if not yet. I use for search in collections, destroys 90% of forychs with nested iffs.
GetComponent (). Bounds.min.y - the bottom of your collider, I mean the minimum ordinate
OnCollisionStay2D docs.unity3d.com/ScriptReference/Collider2D.OnCollisionStay2D.html
OnCollisionExit2D
CollisionContacts docs.unity3d.com/ScriptReference/Collision-contacts.html docs.unity3d.com/ScriptReference/ContactPoint-point.html

OnCollisionStay2D is triggered when the character and platform are moving relative to each other. When a character hits the platform i. with OnCollisionEnter2D, the above event will also work.

So, it turns out, if the character is on the platform, then geometrically his collider and platform collider do not overlap. So, the "bottom of the character" should be EXTREMELY above the point of contact. EVERYTHING!

1) Create a list:

List<Collider2D> GroundColliders = new List<Collider2D>(); 

2) On the OnCollisionStay2D event, we check and, if necessary, add colliders:

 void OnCollisionStay2D(Collision2D coll) { if (!GroundColliders.Contains(coll.collider)) foreach (var p in coll.contacts) if (p.point.y < myCollider.bounds.min.y) { GroundColliders.Add(coll.collider); break; } } 

3) If we no longer intersect with the platform, remove it from the list:

 void OnCollisionExit2D(Collision2D coll) { if (GroundColliders.Contains(coll.collider)) GroundColliders.Remove(coll.collider); } 

4) Guess what we are checking:

 bool IsGrounded { get { return GroundColliders.Count > 0; } } 

Simply, understandably, quite universally, without any tags, rakes, additional gameobjects. Use on health.

Source: https://habr.com/ru/post/279407/


All Articles