Is Bullet Physics for Unity right for me? Subframe logic and callbacks.

Post Reply
lgarczyn
Posts: 2
Joined: Mon Sep 02, 2019 3:29 pm

Is Bullet Physics for Unity right for me? Subframe logic and callbacks.

Post by lgarczyn »

Hi, and thanks for your time.

I'm currently developing a physics-based multiplayer game for mid range hardware on Unity.

I recently gave up on the unity physics engine due to a lack of possible customization.

I need a few things:

Subframe logic:

I have weapons that can fired hundreds of time per second, shot by players moving rapidly. Because of that, I have to interpolate the origin of each object considering the velocity and gravity of the player, but also pretend that the bullets were fired slightly earlier than the current frame. The logic allows me to be frame-rate independent, but I have to use a raycast for the first few meters, and spawn the object further from me. The problem is that the raycast method doesn't allow me to do complex collisions resolution, and if a target moves close enough right after the raycast, they might be missed by the bullet entirely.

Ideally, I should be able to tell the solver that a item x is only to be simulated from an exact time t.

Mid-solver callback:

Collisions can destroy Shields and targets, which are instantly removed from the game. Ideally the solver should be able to realize that a collider is dead during resolution, so that other projectiles may pass through. This means technically that collisions should be resolved in order, however this only needs to happen locally.

I should also be able to deduce the exact time that a collision happened from the callbacks.

Dynamic masks:

Some projectiles may pass through friendly units, but not enemy ones. Ideally I should be able to dynamically create new masks for each team. This is not exactly mandatory, I can deal with implementing that myself with callbacks, or using a limited number of teams.

Dead reckoning:

It's probably feasable, but I'm wondering how other people have fared implementing basic Dead Reckoning in Bullet. Basically only changes in force applied to objects should be broadcasted.

Lastly, if a player is lagging behind, I should be able to slow the simulation for everyone until they catch up.

Other great bonuses would be local slowmo, a parabolic or eliptical raycast function, and a function to get the interpolated position of an object for a given time, and implementation of the unity terrain collider and easy rollback for the server (terrifying prospect I know).

Sorry for the wall of text, English is not my native language, so I tried to be precise, but lacking the vocabulary to be concise. Thanks for reading.
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Is Bullet Physics for Unity right for me? Subframe logic and callbacks.

Post by drleviathan »

Subframe logic

You can't add new objects mid-subframe. Instead: at the beginning of each subframe add the fresh bullets in the right spots after you've done all of your math and logic.

If you're really worried about "tunnelling" because of extrapolated bullet creation behind nearby targets then here is an idea. I don't know if it actually works because I only just thought of it.

Instead of advancing bullets to where they would be at the beginning of the substep, create them where they were supposedly fired (mid previous substep) but give them higher velocity computed Just Right to put them where they should be at the end of the substep. Then, if they manage to not hit anything during their first substep reset their velocity to what it really should be on the next substep. Note, you'll probably want to enable continuous collision detection (CCD) for these fast physical bullets. CCD is off by default but can be enabled on a per-object basis.

Mid-solver callback

I don't think it is a good idea to rely on the order of operations during the substep to perform mid-substep "disabling" of objects, especially in a multi-user environment. My advice would be: try to take shorter substeps and perform all add/remove/update operations between substeps.

I don't believe Bullet provides sub-substep timing of collision events. They happen sometime during the substep and that is all you know. My advice would be to accept this limitation and just try to keep your substeps short enough to minimize whatever problem you're trying to solve here.

Dynamic Masks

Bullet provides 32 bits of collision groups and 32-bits of collision mask. If you need more than that then.. yeah you would have to implement your own special filters/callbacks/whatever. Bullet does have a feature that allows you to bypass collisions between specific pairs of objects: objectA doesn't collide with objectB for example. As I recall the list for objectA to not collide with objectB, C, D, etc is arbitrarily deep, but I wouldn't want to lean too heavily on that feature. I'd be worried about performance if every object was carrying its own deep list.

Changing collision group/mask of an object is not trivial because the info doesn't live on the object itself but on its box proxy in the broadphase. To change the values would require updating the info of the proxy and recomputing overlaps. The simple but somewhat expensive way to do this is to just remove the object from the World and re-add it with the new group/mask. More efficient ways can be had but you need to dig deeper into the broadphase API.

Dead reckoning:

I have successfully implemented dead reckoning (linear and angular) where an object's motion can be ballistically extrapolated over time to figure out where Bullet would put it assuming it really did move sans collisions. To do this accurately you need to break your "step" into the same sub-step durations that Bullet uses.

I'm not sure what you mean by "only changes in force applied to objects should be broadcasted". If you're thinking you would send forces in packets to perform distributed multi-user physics then... it sounds problematic. I assume you've read Glen Fiedler's take on how to do networked physics but if not try these links:

https://gafferongames.com/networked-phy ... d-physics/ (hrm... this link is down as I write this)

https://www.gdcvault.com/play/1022195/P ... Networking

Other great bonuses:

Local slowmo: I don't know how this could possibly work in a multi-user physics simulation.

Parabolic raycast: Bullet does not provide this. I know of one successful implementation of this, however the ray-tracing was done against GameObjects in their own scene rather than using Bullet's spatial tree.

Interpolated position: I'm not quite sure what you want here but: Bullet does supply an extrapolated transform in the btMotionState::setWorldTransform() API where the body is extrapolated forward by any "step remainder", so as to avoid simulation-vs-game-loop aliasing problems.

Unity terrain collider: Dunno what that is. Bullet does have a btHeightfieldShape for a heightfield with regular systematic discretization.

Easy rollback: Bullet does not provide rollback tools or API. You would have to implement.
lgarczyn
Posts: 2
Joined: Mon Sep 02, 2019 3:29 pm

Re: Is Bullet Physics for Unity right for me? Subframe logic and callbacks.

Post by lgarczyn »

Oh man, thanks for the in-depth answer!

Subframe logic

That's a great solution! I would need to calculate a simple speed multiplier to increase the velocity and the gravity (gravity will need to multiplied by the square of the multiplier), so that it achieves nearly the same exact trajectory in a shorter time, with bouncing accounted for.

I would then divide the new velocity by that same multiplier, and reset the gravity. Should Work™.

Does make the prospect of calculating real times of impact worse, though only at short range.

How expensive is CCD? It's probably required for most of what I want to do. Is it possible to have two CCD objects collide with each other?

Mid-solver callback

I'll consider removing items only after the end of the frame, but I kinda wished that the number of steps per frame would have as little effect as possible on the game. Especially since game logic in callbacks is apparently frowned upon.
I don't believe Bullet provides sub-substep timing of collision events.
But would it be possible to, say, deduce the time from the current velocity and position, from the previous velocity, position and gravity? The unity API apparently has CalculateTimeOfImpact, as called in defaultNearCallback. It does like what I'm looking for, but I'm not sure if the data is not already accessible somewhere else, if that's even what I'm looking for.

Dynamic Masks

I'll probably set my own system then. That way I don't need separate projectile pools per team.

Dead reckoning:

Damn, that talk was a bit scary. He mentioned quite a few problems I didn't even consider. Is your implementation of dead reckoning available? I doubt one is already available on unity, but I could may compile it with the plug-in.
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Is Bullet Physics for Unity right for me? Subframe logic and callbacks.

Post by drleviathan »

Subframe logic
Bullet's CCD sweeps a spherical Proxy shape along the path of the center of the Object and if it hits something I think it (a) truncates the Object's forward motion by the fraction where the Proxy hit and (b) includes the sphere's contact points to those of the Object's contact manifolds.

From my experience it is not too expensive (as long as sweeping a sphere through nearby objects is cheap) and it does help solve the tunelling problem.

I have found one exception to the cost: if you use large complex (many tens of thousands of triangles) btBvhTriangleMeshShape instances and you try to sweep a large convex object into the mesh... you will have performance problems. Sweeping a small sphere against a subset of triangles of a complex mesh is ok. In short: if you're using a mesh with many triangles then the dynamic objects that collide against it should be much smaller than the mesh itself.

AFAIK CCD of each object does not sweep against other sweeps, so it only works for the swept proxy against all other objects as if they were at rest. If you want to handle projectile-vs-projectile collisions then maybe instead of CCD you should be using long shapes for you projectiles that are extruded forward in advance of their motion. This is a trick/hack/workaround I've seen used in games when CCD was not available. Perhaps you could get decent results with by blending the two methods.

Mid-solver callback

To be clear: the "game loop frame" is not the same as the "physics step" which is not the same as the "physics substep". I was saying you should restrict your add/remove/change transactions to be at least between the substeps, but you could have multiple substeps per "step" and even multiple steps in a game loop frame if you wanted, although for simplicity you would typically just step once per frame.

For example: if your game loop rate is 30Hz, and if you step once per loop, you could have your substep be 90Hz and you would usually get three substeps for every step.

Note: if you want to provide special handling between substeps you would have to derive CustomDynamicsWorld from (I assume) btDiscreteDynamcsWorld and override some methods there to insert custom logic between substeps. Or... I guess it could be done via a custom btActionInterface::updateAction() method instead, since that would be called once per substep near the end of btDiscreteDynamicsWorld::internalSingleStepSimulation(). Yes, that would be simpler.

Dynamic Masks

If you do use dynamic masks, and if the yes/no collision status doesn't usually change for most objects, then I would recommend trying to make a custom broadphase that allows you to enable/disable bounding box overlaps as per your custom logic. This only because for performance: the earlier you can disable collision checking the cheaper it is.

Dead reckoning

Yes, I will cleanup my dead reckoning logic and provide in a subsequent post.
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Is Bullet Physics for Unity right for me? Subframe logic and callbacks.

Post by drleviathan »

Dead reckoning

Sorry, I looked at the extrapolation code I have and decided: it is wrong. It could only ever work for objects whose inertia tensor has uniform eigenvalues (e.g. the inertia tensor of a sphere or similarly symmetric mass distribution), so I won't post it. A correct generalized version would require some careful work and testing and I don't have time to do that now.

However, it occurs to me: if you only need to interpolate between two known transforms AND the product of velocity * timeStep is not too big (in both linear and angular space), then a simple linear interpolation (lerp) should work.

Similarly, if you only need to extrapolate forward short distance/timeStep then a simple linear extrapolation will work in both spaces.
Post Reply