ANCIENT THREAD! - Physics in Pure ECS

EDIT: This is an old project from years ago, not relevant anymore. DOTS now has its own physics packages

Old post

ECSPhysics aims to be a complete publicly-available 3D physics engine made entirely in Pure ECS for Unity.

It is not currently ready for any sort of real usage. It’s a work-in-progress

Here are some of its current features:

  • Sphere colliders
  • BVH-based broadphase
  • Sequential-Impulses constraint solver

Useful Links:
Github
Handbook/Documentation
Trello


Original Post

I’m in the early stages of prototyping a complete 3D physics engine made specifically for Pure ECS and GPU compute. I think the performance potential of this could be greater than the current physics we have in Unity, and having access to the full source of the physics engine that we can modify to our liking would be an invaluable advantage

However, I’m just curious about one thing: does Unity already have a plan to do this in the relatively short term (let’s say 1-2 years)? Will we eventually have a physics engine that:

  • supports Pure ECS
  • uses GPU compute as much as it should
  • has full source available (based on my previous experience with making character controllers, I cannot stress the importance of this enough! I’d say this is even more important than the performance advantage)

I’d just like to know if my work would be pointless before I start

13 Likes

I would imagine yes to all but the source code, because it is PhysX and therefore owned by nvidia.

It would be silly not to be developing this for unity given they already support computepenetration

EDIT: P.S I am also starting to do this for an RTS and would like to maybe have a catch up on how you get on in a while!

I doubt it will be in the next two years, but at the moment it looks like they want to push everything to pure ecs. I seriously doubt any source would be available for that.

A C# based physics engine with source for pure ECS, with the aim of brute force simple readable code, is something we want to build. We don’t have a plan for GPU based physics.

It would be great to see what you come up with though. Keep us up to date here.

10 Likes

Awesome. I’ll see what I can come up with and will post back in these forums

It’s a start!

https://vimeo.com/270927194

The system is monstruously inefficient right now because I basically have no broadphase (I compare every collider agaist every collider, which is terrible), but I’ve at least reached a point where I have some kind of decent foundation to start building on. Also, I’ll stick to just sphere colliders (and maybe box colliders) for as long as I can, in case I end up doing massive architectural changes. I’ll implement the remaining collision primitives once I’m fairly certain I’ve got something good

For those who are curious, here’s how I’ve arranged things so far:

  • RigidBodySystem: For each rigidbody, handle applying drag and angular drag, and then handle moving the rigidbody position/rotation based on its velocity/angularVelocity

  • UpdateColliderPoseSystem: For each collider (colliders are separate entities from rigidbodies, but they all know which rigidbody “Entity” they belong to), calculate their new worldPos and worldRot based on their relativePos from their associated rigidbody

  • ComputeColliderAABBSystem: For each collider, calculate the AABB (Min, Max, Centroid, etc…)

  • BroadphaseSystem: For each collider, do an AABB test against all the other colliders, and output a NativeArray representing all the pairs of colliders that are potentially overlapping.
    In the near future, I intend on implementing this state-of-the-art BVH algorithm for the broadphase. It is a great fit for the job system or the GPU because it is highly parallelisable. Plus, it doesn’t rely on incremental updates, so it seems fairly simple, safe, and straightforward. We have the popularity of RayTracing to thank for the recent increase of interest in this area of research

  • ContactsGenerationSystem: The first part of the NarrowPhase. Here we take all of the CollisionPairs from the broadphase, and do the actual collision tests. The output of this system is a NativeArray that stores all the collision infos such as contactPoint, collisionNormal, collisionImpulse, overlapDistance, etc, etc…

  • ContactsResolutionSystem: Takes all the CollisionManifolds of the previous step, and actually solves the collisions by applying impulses and displacements to the rigidbodies

Additional notes:

Manual update of systems all of those systems are [DisableAutoCreation]. I handle their creation and updating manually in a “PhysicsSimulationSystem”. This is so that I will be able to do an equivalent of “Physics.Simulate” later on with this physics system. But I haven’t really tested yet if this works well, and I’m still not 100% sure if updating systems manually like that breaks any secret optimizations for ECS/Jobs/Burst

Contacts generation and resolution done in two separate steps There is a good reason why ContactsGenerationSystem and ContactsResolutionSystem are two separate steps; it’s because we sometimes need to be able to do some logic after contact manifolds have been generated, but before the collision is actually solved. Think about a situation where you are making character controllers and want to have complete control over how the character decollides from colliders. A common case is when your character lands on a slope after a jump. Normally, it’ll decollide diagonally because of the angle, so your character will “drift” down the slope a little bit. What you’d really want in that case is to solve collisions 100% vertically instead. You can now add a system between these two that will modify the contact manifolds of your character rigidbodies before they are actually processed and resolved. This is something that we cannot do in current unity physics!

Collision “Events” strategy How will collision “events” work? The plan right now is to build a NativeMultiHashMap<Entity, CollisionManifold> as contacts are generated. Then, other user-made systems can go get this multiHashMap and use the rigidbody entity as key to see if any collisions occured. Another possibility is to store collision events and collisions count in a “CollisionInfos” component that lives alongside the rigidbody, but I’ll need to wait for components to be able to contain fixed-size arrays for that

CPU and GPU My plan right now is to do everything on the CPU for a start. It’s only after having completed the physics engine on CPU that I will start looking into doing GPU compute conversions for parts of the system. The broadphase would be a great candidate for this. I’m having doubts about whether or not the cost of CPU-to-GPU data transfer will defeat the purpose of doing things on GPU in the first place, though. A physics engine isn’t very useful if you can’t even access rigidbody position or velocities because they’re all just on the GPU. Having separate physics worlds (some CPU-only, and some GPU-only with limited data access) is a possibility I’m considering. We’ll see when we get there

An object’s physics representation and visual representation are two separate entities The rigidbodies and the actual meshes are separate entities. Mesh entities simply have a system that makes them follow their associated rigidbody entity with interpolation. In my opinion, interpolation shouldn’t be the responsibility of the rigidbody or the physics engine like it is in unity physics currently. It leads to innumerable headaches when you try to move a rigidbody position manually while still keeping interpolation. I’d much rather have visual object be completely separate from their physics representation. It makes everything so much simpler

How applying forces works Forces and torques will be applied by modifying Velocity and AngularVelocity component values directly. Users can choose if they want to take into account mass or not, or if they want to take into account deltaTime or not (impulse vs addvelocity vs force vs acceleration). But there will be static physics math functions to help calculate the resulting additive vel/angVel of adding a force at a point, for example

Gravity is user-applied Gravity is not some kind of built-in value/functionality in the physics engine. Users are given the responsibility of handling it by themselves with a system that executes right before RigidbodySystem and that applies the desired acceleration to all rigidbodies. I made this decision because there are several games where the gravity is not the same for all objects (think of games like Mario Galaxy, games in space, games with character controllers that have stronger gravity than regular objects so that their jumps feel better, or puzzle games that play with gravity), and in unity physics I’ve frequently had to set rigidbody gravity to 0 and just apply it myself in code instead. I think it’s just much cleaner to apply it ourselves based on our specific needs. With that said… there will probably still be a DefaultGravitySystem that you can choose to activate or not. Maybe it’ll be part of example content instead of the core engine

Kinematic rigidbodies can move with velocity Kinematic rigidbodies can actually be moved with velocity and angularVelocity. This is a nice feature because when you have characters standing on moving platforms, they need to know the velocity of the platform so they can add it to their own velocity. Being able to move kinematics directly with velocity saves you an extra step of having to store the platform’s calculated velocity (or lastPosition) somewhere else. Not a crucial feature, but nice to have

29 Likes

If you make this open source, I would love to contribute. I’m pretty sure other people would as well.

5 Likes

This is something I’ll definitely consider at some point. I’ll wait for the project and the ECS itself to gain more maturity first, though

3 Likes

I second what @starikcetin said. I’ve once implemented a very rudimentary n-body 2D physics for a space shooter game, but I did have a lot of the physics engine take over on what I did. Looking at your design you haven’t catered for the different possible layers yet?

2 Likes

yeah I don’t have a notion of layers at this time, but it’s definitely something I’ll add soon. And we can finally have separate physics & rendering layers! And not be limited to 32 layers

I’ll also have a look at what UE4 does with its collision layers for inspiration, because I think they offer more granular control than what we’re used to

https://www.unrealengine.com/en-US/blog/collision-filtering

I am just about to start an AABB System for sprites. Did you role your own transform system or did you use the build in one that does not account for scale (or was this added?)

I’m using my own equivalent of a transform system for rigidbody and collider entities, but I’ll see if it makes more sense to just use the built-in one everywhere

Nice work ! :slight_smile:
I didn’t know we could already manually update systems without breaking things appart…
I would love what Unity’s team has to say about that, if we should do it or not, or if they will add some API to support this in a good way.

Pretty nice start. There is gonna be a huge improvement by using a spatial partitioning (like the boid ECS sample) to only check nearby colliders but also a flag IsMoving to avoid looping on inactive colliders, ECS will be perfect for that use case.

I have dabbled with GPU colliders a few weeks ago, it produce some nice results. (Yep, I’m using your KCC demo scene, it’s a pretty good playground :))
JoyfulUglyDunnart
I’ve got about 200k particles checking each 1k triangles, 40 capsule and 5 sphere colliders at 1.7ms.
I’ve got the same problem here, without partitioning it won’t scale well and making that data structure on the GPU won’t be trivial.

8 Likes

Gonna use octree for collision partitioning?

I’ll use a BVH approach for this. It’s a type of space partitioning that is based on grouping bounding boxes in a tree structure of pairs that are relatively close to eachother, rather than just subdividing the space like an octree

My research suggest that this approach usually beats octrees, bsp trees and kd trees in terms of total efficiency (construction + traversal), in the context of both physics engines and raytracing

I’m in the middle of implementing my BVH construction in the broadphase, and I came across a very interesting metric.

I wrote some algorithm for calculating the morton codes of all of my collider centers, and them sort them in ascending order using a radix sort. It’s a rudimentary initial implementation, so still not optimized or parallelized at all. But here’s what’s interesting:

Literally the only thing that changes between these two tests is adding [ComputeJobOptimization] on the job

Conclusion: holy crap!

Edit: I actually just managed to split that cost nearly in half, but it affects both burst and non-burst so the speedup ratio is the same

8 Likes

We’re in for a hell of a ride once all the burst technology gets stable and onto all the consoles / high-end mobiles.

2 Likes

In regards to events our plan is to use components as events. You can use EntityCommandBuffer to add components from jobs and apply them later in the frame. Currently its not optimal in terms of performance, but we will make a fast path for add / remove components for components that get added and removed temporarily.

7 Likes

The playerloop integration code simply calls the public void Update(); method so ts not gonna have any perf downsides.
That said, we definitely want to support making systems properly hierarchical. For the same reason of being able to update a single system and it running all sub-systems.

1 Like