Avoiding sttutering or sinking when Collision between trigger and kinematic body occurs

I’m doing some tests trying to avoid the use of raycasts. I’m trying just to let a box fall (kinematic body), and make it stand on another big box (floor). You can think it as a player colliding with floor. I achieved success using raycast for this but I wanted to try doing it with own unity collision system avoiding any player sttutering or sinking.

The code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour
{

Vector2 _velocity = Vector2.zero;
public Vector2 _acceleration = new Vector2(0, -10);
Rigidbody2D _rb;

    void Awake()
    {
        _rb = GetComponent<Rigidbody2D>();
    }
    // Use this for initialization

    // Update is called once per frame
    void FixedUpdate ()
    {
        Debug.Log("Moved");
        _velocity += _acceleration * Time.deltaTime;
        _rb.position=_rb.position + _velocity * Time.deltaTime;
    }

    void OnTriggerEnter2D(Collider2D col)
    {
        Debug.Log("trigger Enter");

        Vector3 pos = _rb.position;

        float maxY=col.GetComponent<Collider2D>().bounds.max.y;
        Vector3 newPos = new Vector3(0, maxY,0);

        _rb.position=newPos;

        _velocity.y = 0;
    }
}

Really simple code. The problem is:

  1. If I use OnTriggerStay instead of OnTriggerEnter it works correctly but this is too cpu intensive.

  2. If I use OnTriggerEnter, it seems that when I move the box over the floor they are still sharing one edge (at y=0) and though, they are still colliding colliding and falling box (player) starts to sink next frame because no more OnTriggerEnter will be called.

  3. If I use OnTriggerEnter with for example a delta of 0.1f, it stutters (you have to really get close to notice it because I use 1 pixel == 1 unity pixel but it happens).

So, Is there any possibility to accomplish total balance of the player on the floor without using OnTriggerStay?

Note: Player has its pivot at the bottom.

Note: The floor top is set at 0.

Thanks in advance.

I use a trigger on the “non moving parts” because I don’t want to use unity physics (only the collisiion detection part) and don’t need the information that OnCollisionXXXX provides.

Cheers.

You could just use a PlayerController. It has everything you need, gravity, good collision detection, etc.

You’re really not using the system as it is meant to be used, nor doing things well at all.

Players or other sensitive elements should use Continuous (maybe even dynamic) Collision Detection (RigidBody settings).

The FixedUpdate intervals also are not a multiple of the Update interval, so you might randomly have one or two FixedUpdates between two render update.

You don’t have any detection that your player is currently on a surface, and you use a bad approximation of physics, not even offset by doing them in small steps. Every frame your object sinks in the object, and is jumped back up.

removed false statement about OnTrigger calls

OnTriggerEnter also won’t be called again if you don’t move your object high enough to actually get out of the collider.

Have you actually checked that OnTriggerStay is too CPU intensive? That would surprise me a lot.

If you really want to do thing your way, activate interpolation on your RigidBody2d, use accurate physics movements, do them in small steps, and check yourself that you just moved in a collider. You can do that by getting a list of colliders in a reasonable range, and checking every step that you moved in a collider.

Once you are on a collider, you should check every frame that you still are on said collider, and round your position to the height of the collider using a “stayOnGroundForce”
variable, that you can easily modify. You should still check other colliders for horizontal movement in a similar way.

And in the end you would have just reimplemented PlayerController. Just use what is available to you.