Access EntityRigidBody by EntityId [SiO2]

I’d like to control the restitution (and probably other parameters) of an EntityRigidBody through its EntityId. Looking at BulletSystem, it doesn’t seem like there is any way to access an EntityRigidBody at all except through a ControlDriver (which I definitely don’t want to do in this case). What should I do?

I don’t know bullet that well. Does it let you control that from the body?

Yup, restitution is controlled by the rigid body.

Is this something you want to set once during creation or throughout the lifetime of the object?

The former is trivial, the latter could be trickier.

Actually, it could be it’s the same answer:

public void setupObject( EntityId objectId, Function<EntityPhysicsObject, ?> setup )

So, from some other system or whatever where you need to change the restitution for a particular body:

bulletSystem.setupObject(myEntityId, (body) -> do the stuff);

…and the bullet system will make sure it happens on the right thread and at the right time. (If for some reason the entity is brand new created then the physics system could technically not know about it yet but the above would still work… it will try 100 game loop frames before giving up.)

1 Like

That worked, thanks! :smiley:

public class RestitutionSystem extends AbstractGameSystem {
    
    private EntityData ed;
    private BulletSystem bullet;
    private EntitySet entities;
    
    @Override
    protected void initialize() {
        ed = EntityUtils.getEntityData(getManager());
        bullet = getManager().get(BulletSystem.class, true);
        entities = ed.getEntities(ShapeInfo.class, Mass.class, Restitution.class);
    }
    @Override
    protected void terminate() {
        entities.release();
    }
    @Override
    public void update(SimTime time) {
        if (entities.applyChanges()) {
            entities.getAddedEntities().forEach(e -> applyRestitution(e));
            entities.getChangedEntities().forEach(e -> applyRestitution(e));
        }
    }
    
    private void applyRestitution(Entity e) {
        float r = e.get(Restitution.class).getRestitution();
        bullet.setupObject(e.getId(), (EntityPhysicsObject t) -> {
            if (t instanceof EntityRigidBody) {
                var body = (EntityRigidBody)t;
                body.setRestitution(r);
            }
            return null;
        });
    }
    
}

One question, though… is there a particular reason why BulletSystem does not allow outside systems to access EntityRigidBodies directly? I’m doing that with my ModelViewState implementation to allow other states to access models directly, but I’m not sure that is considered good practice, ecs wise.

a) it’s technically not good ECS practice for systems to share their internal workings.

b) in the case of the bullet system, the bodies might be being managed on a totally separate thread and raw access would potentially break a bunch of things in really subtle ways.

In Mythruna, I also allow other states (which have systems) to access ModelViewState created models… but I also had to do a bunch of extra work to support delayed access, reference counting, etc… Sometimes the other system wants a model before ModelViewState has seen it and sometimes ModelViewState is done with a model before some other state. These are why (A) is the way it is… but I’m willing to deal with the pain to have shared Spatials in some case.

(Note: that there are other cases where I position something relative to a model that I DON’T use the model view state’s spatials and just update the position separately. The code is always cleaner this way but it’s not always possible to do well, ie: cases where that other thing doesn’t have a position but knows what spatial its on.)

1 Like