Home

Awesome

LeoECS Lite Physics

This is a simple Unity physics events emitter for Leopotam ECS Lite framework. No more need to create MonoBehaviour scripts for physics events handling - just follow a few simple steps to do it with this tool.

Installation

You can install this repository via Package Manager:

Package Manager -> Add package from git URL...

Fill the opened field with this line:

https://github.com/supremestranger/leoecs-lite-physics.git

If you can't / don't want to use Package Manager or Git, you can just download the repository and add it to your project.

Checkers

Checker is a MonoBehaviour script that contains a specific Unity physics event method.

You need to attach a concrete Checker to any GameObject that emits any Unity physics events.

All Checkers:

All 2D checkers work in the same way.

Events

When Unity Physics event is raised, the EcsPhysicsEvents static class creates a new entity-event with a specific component like OnCollisionEnterEvent or OnTriggerStayEvent.

The event component has various amount on fields based on the event.

OnCollision

public GameObject senderGameObject;
public Collider collider;
public ContactPoint firstContactPoint;
public Vector3 relativeVelocity;

Note: The contact point is in world-space and not available in OnCollisionExit and OnCollisionExit2D events!

OnTrigger

public GameObject senderGameObject;
public Collider collider;

OnControllerColliderHit

public GameObject senderGameObject;
public Collider collider;
public Vector3 hitNormal;
public Vector3 moveDirection;

All 2D events work in the same way.

But before diving into handling all of this stuff, you need to initialize the EcsPhysicsEvents in your Startup script like this:

sealed class EcsStartup : MonoBehaviour
{
    private EcsWorld ecsWorld;
    private EcsSystems ecsSystems;
        
    private void Start()
    {
        ecsWorld = new EcsWorld ();
        ecsSystems = new EcsSystems (ecsWorld);
        // initialization of emitter.
        EcsPhysicsEvents.ecsWorld = ecsWorld;
            
        ecsSystems
            // your systems
            .Add(new TestSystem())
            .Init();
    }

    private void FixedUpdate()
    {
        ecsSystems?.Run ();
    }

    private void OnDestroy()
    {
        if (ecsSystems != null)
        {
            // don't forget to get rid of this reference.
            EcsPhysicsEvents.ecsWorld = null;
            ecsSystems.Destroy();
            ecsSystems = null;
            ecsWorld.Destroy();
            ecsWorld = null;
        }
    }
}

You can get data of event in your systems:

public class TestSystem : IEcsRunSystem
{
    public void Run(EcsSystems ecsSystems)
    {
        var filter = ecsSystems.GetWorld().Filter<OnCollisionEnterEvent>().End();
        var pool = ecsSystems.GetWorld().GetPool<OnCollisionEnterEvent>();
        
        foreach (var entity in filter)
        {
            ref var eventData = ref pool.Get(entity);

            eventData.collider.gameObject.SetActive(false);
        }
    }
}
 

You can DelHere some events if you want or you can use DelHerePhysics() for DelHere'ing all events:

private void Start()
{
    ecsWorld = new EcsWorld ();
    ecsSystems = new EcsSystems (ecsWorld);
    // initialization of emitter.
    EcsPhysicsEventsEmitter.ecsWorld = ecsWorld;
            
    ecsSystems
        // your systems
        .Add(new TestSystem())
        // delhere all unity physics events.
        .DelHerePhysics()
        .Init();
    }

FAQ

I attached the Checker to GameObject, but it doesn't register any physics event

Keep in mind that one of your GameObjects must have kinematic Rigidbody component attached.

By the way, for OnTrigger and OnControllerColliderHit events the CharacterController component is fine.

image

Some of my events being registered multiple times. For example, OnTriggerEnter

This cannot be fixed as events raised by Unity Physics engine, so you need to think how to fix it on your side.

You can try to create some kind of timer that is started when the event is raised and ignore events while the timer is running.