This is a simple Unity physics events emitter for Leopotam ECS framework. No more need to create MonoBehaviour scripts for physics events handling - just follow a few simple steps to do it with this tool.
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-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.
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.
OnTriggerEnterChecker
- responsible forOnTriggerEnter
eventOnTriggerStayChecker
- responsible forOnTriggerStay
eventOnTriggerExitChecker
- responsible forOnTriggerExit
eventOnCollisionEnterChecker
- responsible forOnCollisionEnter
eventOnCollisionStayChecker
- responsible forOnCollisionStay
eventOnCollisionExitChecker
- responsible forOnCollisionExit
eventOnControllerColliderHitChecker
- responsible forOnControllerColliderHit
(only forCharacter Controller
objects) event
All 2D checkers work in the same way.
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.
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
andOnCollisionExit2D
events!
public GameObject senderGameObject;
public Collider collider;
public GameObject senderGameObject;
public Collider collider;
public Vector3 hitNormal;
public Vector3 moveDirection;
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
{
private EcsFilter<OnCollisionEnterEvent> filter;
public void Run()
{
foreach (var i in filter)
{
ref var eventData = ref filter.Get1(i);
eventData.collider.gameObject.SetActive(false);
}
}
}
You can OneFrame
some events if you want or you can use OneFramePhysics()
for OneFrame
'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())
// oneframe all unity physics events.
.OneFramePhysics()
.Init();
}
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.
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.