[SOLVED] Zay-Es Design with game states sharing a velocity component

I’m using zay-es and building off of the Asteroid Panic example.
I am trying to add other velocity based behaviour to some of the entities - for example making things move in a circle.

The zay-es documentation at https://github.com/jMonkeyEngine-Contributions/zay-es/wiki/Documentation#rules-of-thumb suggests that only one system produces a component for the same entity.
In my situation i have the collision system handling velocity component changes and now also a “MoveInCircleState” appstate changing the velocity component as well. (And just to note a physics state which handles the updated position based off of the velocity component)

As I’m new to entity systems I’m not sure what I should be doing to prevent this overlap.
(Just to be clear, its not causing any actual in game issues yet)

Thanks,
murph9

ECS is a complex beast, and these overlaps are easily the most difficult hurdle.

While it may not cause any gameplay issues now, it will in the future. Modifying components from multiple states means that the order in which states are run is absolutely important and this kills the single biggest advantage of ecs: incredibly simple multithreading. When you add several other systems that modify the velocity eventually you’ll have them trample over eachother and it will NOT be clear which one is doing it and why.

Without seeing your actual code it is difficult to determine how to best handle your specific case, but here is probably the most common practice for physics stuff:

Use “messenger” entities. You’ll have an “ApplyForce” component which will store the force and the entityid of it’s target. You’ll create many of these and they’ll be destroyed as soon as they are consumed. Your collision state will create a force when a collision is detected, and your circle state will apply a force to move the entity in the desired direction. You’ll have a 3rd state that simply iterates through all the “applyforce” entities, accumulates all forces per target in a map (eid, vec3) and every time you find multiple forces with the same target you just add em together. After all the forces were accumulated you apply the final result to the eid as a new velocity component.

These messenger systems are sometimes required but just as often can be a crutch to several poorly thought out systems.

Okay its good to know i was on the right track, as I had a thought to add an intermediate force type like you said. I have messenger like entities for 2 other systems.

I’ll need to plan it out to see if i can get it to work right.

This is why i originally asked the question, while adding more velocity based AppStates i could see it already becoming a mess.

1 Like

cant you replicate the driver interface and just have a state with one or more drivers, attached to game objects, where you each update cycle, define the buttons the driver “pushes” - and if you just make it a “circledriver” you could pick that up specifically in your physics state and handle it whichever way you want?

maybe im out of the loop

As Need for speed heat came out yesterday so i haven’t worked on this yet…

My current understanding of Entity systems is that “pick that up in your physics state” is making the physics state do too much work.

The idea seems that there will be a new component called something like ‘Forces’ which has a list of forces that each system can add to the entity. And a new ForceSystem which just adds them together to make the Velocity component.

So far just thinking about it, I’m confused that now everything will have to use the new ‘Force’ component which complicates fixed speed items. (otherwise the ForceSystem will clash in setting velocity components again, coming back to the same problem)

Well, one can err the other way and put too much in the ES, also. You just have to decide what is really game data and what is game function.

For example, you wouldn’t model the forces on every car wheel in the ES. The physics system would have some idea of a vehicle and the ES would just “drive” it.

Similar things can be done with characters, mobs, etc… which is why a lot of the Zay-ES physics examples have this idea of a ‘driver’ that hooks into the physics engine. It translates game data into physics interaction. So character knows “walk this way” and the driver knows how to make the character do that.

Edit: and note, this doesn’t preclude having impulse and velocity for uncontrolled objects or objects that just follow normal physics laws otherwise (like asteroids or bullets, etc.)

1 Like

Regarding this specifically, I’m wondering how you are thinking about forces. Is your concern that they will be cumulative frame over frame?

It’s fine to have velocity components set by many systems but then they would be targeted components and not directly on the entity. The wouldn’t represent the actual velocity they’d represent some part of cumulative target velocity.

While it’s nice in simple examples, and the pos = pos + vel * t example makes a great example for the kinds of decomposition an entity system does, it’s only going to be simple games that actually implement physics this way.

Anyway, even if you really want a velocity component on specific entities then it just means you have different types of components that your velocity-controlling system can use… and they are just cumulative forces but maybe also impulses or fixed velocity, etc…

Sometimes it turns out we aren’t asking the right questions in the end… and the question is not an ES question but a “what do you actually want to do?” question.

I’m expecting to remove the component after use. (just like any ‘damage’ like component onto a ‘health’)

Its rather simple, i have the Position and Velocity components from the AsteroidPanic example.
So basically I’m stuck trying to figure out how to make some of the spawned objects move in a circle around a moving point without stepping over the velocity system still in place. While still having the normal collision and hit detection of the other objects.

This is all in the sake of learning entity systems, so even if its not the best way im trying to learn how an entity system should do it. (even if there is a simpler method)

If the component is on a tagging entity then you shouldn’t remove it automatically. Let the entity decide when it should be removed using a Decay component or similar.

That way you could have a force last one frame, 5 seconds, several hours, forever… whatever you need.

Okay okay, but if you only ever wanted to be an impulse that would be valid? (because moving in circle almost never has a constant force)

But in other words: Force(Vec3 v, float length)
and just like the decay component it has a percentage completion using the system’s update tpf.

I’m going to look this up i think.

Tagging entity is also referred to as “messenger entity” by others in earlier comments.

These are entities that point at something else. Their job is to hold information that is applied to some other entity (like damage, forces, etc.) Some system accumulates them and applies the result to the target.

So an Entity with a Force(targetEntity, 50) and a Decay(5 seconds) component would apply force 50 until the decay system kills it (in 5 seconds).

I don’t remember if the asteroid panic example had a decay system but it’s common enough that SiO2 includes one by default:

By the way, what is the thing that is supposed to move in a circle?

Just imagine that the rocks in asteroids just are a little harder that they move around a center point, kind of like orbiting but nothing that fancy.
At the moment they just move in a direction that rotates around using:

<component>.updateAngle(tpf);
float rad = <component>.getAngle();
e.set(new Velocity(new Vector3f(FastMath.sin(rad), FastMath.cos(rad), 0).mult(<component>.getSpeed())));

And component stores the current angle gets updated when called (i have a guess this is against ES but its not a big problem yet)

(decay component is in both zay es examples too)

So using the entity system to manage the components as well, interesting.
Ah that’s cool, although my brain might not be ready to understand how to apply that yet.

My first thought is would one find the tagged entity if they only have the base entity, or is that missing the point?

I have understanding to do it seems…

One thing is that the Asteroid Panic physics engine is a velocity-only engine. Even ship acceleration is simulated in the ship control on the user interface side.

A physics engine that supports acceleration (necessary for forces/impulses) would need to be changed to have acceleration and components that operate on that. Impulses could change velocity directly and acceleration would affect velocity over time.

But it requires altering the physics system to support these things. It’s not something that one should do externally. At that point, the velocity could become a private piece of data of the physics system. There’s no harm in keeping it as a component in this example but recognize that nothing but the physics system will be setting it… and hardly anything would be looking at it. (Though it’s common enough for some systems to care about current velocity.)

Edit: I guess many of the examples don’t bridge this gap but Silicon Gemini comes the closest. It at least supports impulses upon object creation:

…it’s not a stretch to support them on tagging entities.

Thanks for the class reference i skimmed it and i mostly understand it.

and a little brain dump to make sure im on the right track

I’m comfortable with physics systems enough to be able to modify the whole entity system to use accelerations, as an ForceSystem is basically just a copy of the vec system but it starts with accel component and ends with velocity. The collision system will just have to set very short accel components.

But now a lot of things are setting the ‘Accel’ Component which is against the point.
So the suggestion is to use ‘tagged entities’.

In this case multiple things can create tagged entities which apply forces indirectly to the base entity. This stops the components from being overwritten by other classes, and allows you to set decay and modifiers to the sub entities without having to do any work. I.e. components have components… (hopefully that doesn’t get too deep)

If thats right i think i know where to go to next.


Edit:
So in my original example, if i could have read it correctly the first time, tagged entities could be used to set velocities from specific places without overriding each other.
Giving the specific working of:

Two systems should not be producing the same component type for the same entities.

from the rules of thumb of the documentation.
Because we aren’t setting the component we are setting a tagged component they don’t encroach on each other.

Yes, the “don’t set the same component from multiple systems” is for a single entity. So SystemA and SystemB should not be setting component Foo on a specific same entity, 123.

It’s ok for SystemA to create its own entity to set Foo on and SystemB to create its own entity to set Foo on. No complications arise with ordering, threading, or anything else in that case.

And yes, you could treat velocity as a tagging component also… though in the end you will likely want acceleration and impulses, anyway.

1 Like

Yeah i understand that, couldn’t imagine a physics engine which can only just blindly add velocities together being that useful.

Thanks for the help, hopefully i’ll have something to show for it soon ™.

1 Like

My attempt at a ForceState: (some extra game stuff, variables and extra fluff removed)

public class ForceState extends BaseAppState {

    private EntityData ed;
    private EntitySet entities;

    @Override
    protected void initialize(Application app) {
        ed = getState(EntityDataState.class).getEntityData();
        entities = ed.getEntities(Force.class);
    }
    @Override
    protected void cleanup(Application app) {
        entities.release();
        entities = null;
    }
    @Override
	public void update(float tpf) {
        entities.applyChanges();

		for (Entity e : entities) {
            Force f = e.get(Force.class);
            EntityId affected = f.getAffects();

			Velocity vel = ed.getComponent(affected, Velocity.class);
            if (vel == null) {
                vel = new Velocity();
			}
            Vector3f linear = vel.getLinear();
            linear.addLocal(f.getForce().divide(1).mult(tpf)); // mass = 1 for now
            ed.setComponent(affected, vel);
        }
    }
}

public class Force implements EntityComponent {
    private final Vector3f dir;
    private final EntityId affects;
	
    public Force(EntityId affects, Vector3f dir) {
        this.affects = affects;
        this.dir = dir;
    }
	
    public EntityId getAffects() { return this.affects; }
    public Vector3f getForce() { return this.dir; }
}

Just making sure i understand the tagged entity stuff correctly (and hoping this helps other people).

Used like this:

Entity e1 = {{important entity that we are affecting}};
//pretending downward gravity for this example, which lasts for 1 sec and is the normal value
ed.setComponent(ed.createEntity(), 
    new Force(e1.getId(), new Vector3f(0, -9.81f, 0)),
    new Decay(1000));

//add another random force
ed.setComponent(ed.createEntity(), 
    new Force(e1.getId(), new Vector3f(1, 0, 0),
    new Decay(1)); //i don't use this in my code, so 0 could be valid here - i haven't checked

//these should both apply to the same {{important entity}}