#StackBounty: #entity-system #events #entity-component Event handling in Pure Entity Component Systems, is this approach correct?

Bounty: 100

I want to ask if the following is an effective way to architect event propagation using an ECS?

Here is a hypothetical collision scenario using an ECS.

Components:

class Collider {
    public var rect:Rectangle;
}

and

class Health {
    public var health:Int;
}

Now for the behaviour logic:

We can create entities with Collider and/or Health components.

Some ColliderSystem handles entities (more specifically, nodes) with Collider components. It deals with handling collision logic and determining if two Collider component rectangles overlap.

Moreover, if an entity with a Collider component has a Health component, the Health component’s value should decrease.

How would I implement this behaviour?


I see three ways to approach it, 2 bad, 1 good.

  1. Bad idea 1: We could check for a collision on all ColliderHealthNodes in a HandleCollisionsSystem each frame, but this seems like a waste of computation. The value likely won’t be changing every frame.

  2. Bad idea 2: Instead of an events system however, we can use the ECS to pass this logic via system registration. Our HandleCollisionsSystem could add a Collided component (really just a tag) to the Collider component’s entity. Then our HandleCollisionsSystem would be registered to our ECS with an aspect of <Collider, Health, Collided>.

    Besides this looking like an overuse/abuse of ECS, it also silently couples logic between systems (how do we know that CollisionSystem will add Collided component tags to the entities of the ColliderNodes it processes?) How do we know that our HandleCollisionsSystem needs to have an aspect that includes a Collided tag? CollisionSystem and HandleCollisionsSystem need to know each others inner workings and so become logically, but invisibly, coupled.

  3. Good idea (?): The approach that makes the most sense in my mind is to use an event-listener pattern and to have our CollisionSystem broadcast CollisionEvents, while our HandleCollisionsSystem can listen to CollisionEvents. The implementation is described below:


We’d create an enum:

enum CollisionEvent {
    BEGIN_COLLISION;
    // ... could have more types
}

And we create our CollisionSystem like so

//aspect:<Collider>
class CollisionSystem {

    // some collision determining logic to determine if a Collider
// is being collided with -> calls the broadcastCollisionEvent function
// on those Colliders that are colliding

    function broadcastCollisionEvent(event:CollisionEvent, collider:Collider){
        eventSystem.broadcastEvent(event, collider)
    }
}

We’d then have an interface

interface CollisionEventListener {
    function handleCollisionEvent(event:CollisionEvent, collider:Collider);
}

And our HandleCollisionsSystem would look like

//aspect:<Collider, Health >
class HandleCollisionsSystem implements CollisionEventListener

    public function handleCollisionEvent(collisionEvent:CollisionEvent, collider:Collider) {
        colliderHealthNode = findNodeForColliderComponent(collider)
        switch(collisionEvent){
            case BEGIN_COLLISION:
                assocNode.health.health -= X; // some computation
            // other cases
        }
    }

Our HandleCollisionsSystemthen gets registered as a listener for CollisionEvents to the EventSystem. When the CollisionSystem broadcasts a CollisionEvent, the EventSystem will propagate that call to the HandleCollisionsSystem to handle.

Is this the best approach for handling event propagation between systems?

If it isn’t: is there a better way?

If it is: how would we implement findNodeForColliderComponent()?:

Would we always register ColliderHealthNodes within a Collider->ColliderHealthNode map within our HandleCollisionsSystem upon registration to be looked up later?


Note 1 Specifically referring to a ECS to mean pure ECS: that is, all behaviour would be encompassed by systems and all components are data-only. Systems don’t have access to entities directly and only operate on “nodes”- bags of components that match their respective aspect; ie ColliderSystem operates on “nodes” with only a Collider component, and HandleCollisionsSystem operates on “nodes” with both a Collider and Health component.

Note 2 In this simplification, it may look like merging CollisionSystem and HandleCollisionsSystem would make sense, but the separation is there to allow extension to a more complex scenario where we have multiple different HandleCollision systems that care about CollisionEvents and affect different aspects.


Get this bounty!!!

#StackBounty: #c++ #lua #entity-component How to store Lua script's inner state?

Bounty: 50

Situation:

  • I am working on an Entity-Component system, and I am using LuaBridge as a Lua binder.

  • There is only one Lua State.

  • Currently when I update the game objects, I just check whether it has a script defined or not. If there is, I call luaL_dostring() on it, and I call its update() function.

  • I have a script, where I declare a global variable in its start() (it is called when the script runs for the first time), and increment it at every update() then print it out

Question:

  • I would like to achieve separated inner state saving for my scripts.
    • For example If I add the same script to two different game objects, currently the printed out numbers will be 1,2,3,4,5,6 instead of 1,1,2,2,3,3, etc.
    • This is because they use the same Lua State (correct me if I am wrong)

    • But as I heard it’s not a good practice to have a lua state for every script because If I just have 5 scripts, and I add these to 3 different game objects, there would be already 15 lua states.

How should I achieve my goal?


Get this bounty!!!

#StackBounty: #c++ #lua #entity-component How to store Lua script's inner state?

Bounty: 50

Situation:

  • I am working on an Entity-Component system, and I am using LuaBridge as a Lua binder.

  • There is only one Lua State.

  • Currently when I update the game objects, I just check whether it has a script defined or not. If there is, I call luaL_dostring() on it, and I call its update() function.

  • I have a script, where I declare a global variable in its start() (it is called when the script runs for the first time), and increment it at every update() then print it out

Question:

  • I would like to achieve separated inner state saving for my scripts.
    • For example If I add the same script to two different game objects, currently the printed out numbers will be 1,2,3,4,5,6 instead of 1,1,2,2,3,3, etc.
    • This is because they use the same Lua State (correct me if I am wrong)

    • But as I heard it’s not a good practice to have a lua state for every script because If I just have 5 scripts, and I add these to 3 different game objects, there would be already 15 lua states.

How should I achieve my goal?


Get this bounty!!!

#StackBounty: #c++ #lua #entity-component How to store Lua script's inner state?

Bounty: 50

Situation:

  • I am working on an Entity-Component system, and I am using LuaBridge as a Lua binder.

  • There is only one Lua State.

  • Currently when I update the game objects, I just check whether it has a script defined or not. If there is, I call luaL_dostring() on it, and I call its update() function.

  • I have a script, where I declare a global variable in its start() (it is called when the script runs for the first time), and increment it at every update() then print it out

Question:

  • I would like to achieve separated inner state saving for my scripts.
    • For example If I add the same script to two different game objects, currently the printed out numbers will be 1,2,3,4,5,6 instead of 1,1,2,2,3,3, etc.
    • This is because they use the same Lua State (correct me if I am wrong)

    • But as I heard it’s not a good practice to have a lua state for every script because If I just have 5 scripts, and I add these to 3 different game objects, there would be already 15 lua states.

How should I achieve my goal?


Get this bounty!!!

#StackBounty: #c++ #lua #entity-component How to store Lua script's inner state?

Bounty: 50

Situation:

  • I am working on an Entity-Component system, and I am using LuaBridge as a Lua binder.

  • There is only one Lua State.

  • Currently when I update the game objects, I just check whether it has a script defined or not. If there is, I call luaL_dostring() on it, and I call its update() function.

  • I have a script, where I declare a global variable in its start() (it is called when the script runs for the first time), and increment it at every update() then print it out

Question:

  • I would like to achieve separated inner state saving for my scripts.
    • For example If I add the same script to two different game objects, currently the printed out numbers will be 1,2,3,4,5,6 instead of 1,1,2,2,3,3, etc.
    • This is because they use the same Lua State (correct me if I am wrong)

    • But as I heard it’s not a good practice to have a lua state for every script because If I just have 5 scripts, and I add these to 3 different game objects, there would be already 15 lua states.

How should I achieve my goal?


Get this bounty!!!

#StackBounty: #c++ #lua #entity-component How to store Lua script's inner state?

Bounty: 50

Situation:

  • I am working on an Entity-Component system, and I am using LuaBridge as a Lua binder.

  • There is only one Lua State.

  • Currently when I update the game objects, I just check whether it has a script defined or not. If there is, I call luaL_dostring() on it, and I call its update() function.

  • I have a script, where I declare a global variable in its start() (it is called when the script runs for the first time), and increment it at every update() then print it out

Question:

  • I would like to achieve separated inner state saving for my scripts.
    • For example If I add the same script to two different game objects, currently the printed out numbers will be 1,2,3,4,5,6 instead of 1,1,2,2,3,3, etc.
    • This is because they use the same Lua State (correct me if I am wrong)

    • But as I heard it’s not a good practice to have a lua state for every script because If I just have 5 scripts, and I add these to 3 different game objects, there would be already 15 lua states.

How should I achieve my goal?


Get this bounty!!!

#StackBounty: #c++ #lua #entity-component How to store Lua script's inner state?

Bounty: 50

Situation:

  • I am working on an Entity-Component system, and I am using LuaBridge as a Lua binder.

  • There is only one Lua State.

  • Currently when I update the game objects, I just check whether it has a script defined or not. If there is, I call luaL_dostring() on it, and I call its update() function.

  • I have a script, where I declare a global variable in its start() (it is called when the script runs for the first time), and increment it at every update() then print it out

Question:

  • I would like to achieve separated inner state saving for my scripts.
    • For example If I add the same script to two different game objects, currently the printed out numbers will be 1,2,3,4,5,6 instead of 1,1,2,2,3,3, etc.
    • This is because they use the same Lua State (correct me if I am wrong)

    • But as I heard it’s not a good practice to have a lua state for every script because If I just have 5 scripts, and I add these to 3 different game objects, there would be already 15 lua states.

How should I achieve my goal?


Get this bounty!!!

#StackBounty: #entity-system #events #entity-component Event handling in Entity Component Systems, GUI scenario, is this approach corre…

Bounty: 100

I want to ask if the following is a an effective way to architect event propagation using an ECS?

Here is a hypothetical GUI system using an ECS.

Components:

class Btn {
    public var rect:Rectangle;
    public var pressed:Bool;
}

and

class Graphic {
    public var frame:Int;
}

Now for the behaviour logic:

We can create entities with Btn and/or Graphic components.

Some BtnSystem handles entities with Btn components. It deals with handling mouse events and determining if they land within a Btn component rectangle and deciding if a Btn component is pressed.

Moreover, if an entity with a Btn component has a Graphic component, the Graphic component’s frame should be set to 2 if pressed, 1 if not pressed.


I see three ways to approach it, 2 bad, 1 good.

  1. Bad idea 1: We could check for a change in pressed value on all BtnGraphicNodes in a BtnGraphicSystem each frame, but this seems like a waste of computation. The value likely won’t be changing every frame. The problem looks like it lends itself to an event system.

  2. Bad idea 2: Instead of an events system however, we can use the ECS to pass this logic via system registration. Our BtnSystem could add a Down component (really just a tag) to the Btn component’s entity. Then our BtnGraphicSystem would be registered to our ECS with an aspect of <Btn, Graphic, Down>.

    Besides this looking like an overuse/abuse of ECS, it also silently couples logic between systems (how do we know that BtnSystem will add Down component tags to the BtnNodes it processes?) How do we know that our BtnGraphicSystem needs to have an aspect that includes a Down tag? BtnSystem and BtnGraphicSystem need to know each others inner workings and so become logically, but invisibly, coupled.

  3. Good idea (?): The approach that makes the most sense in my mind is to use an event-listener pattern and explicitly declare that our BtnSystem can broadcast BtnEvents, and our BtnGraphicSystem can listen to BtnEvents. The implementation is described below:


We’d create an enum:

enum BtnEvent {
    PRESSED
    RELEASED
}

And an interface

class BtnEventBroadcaster {
    function broadcastBtnEvent(event:BtnEvent, btn:Btn);
}

And we create our BtnSytem like so

//aspect:<Btn>
class BtnSytem implements BtnEventBroadcaster {

    // some mouse handling logic to determine if a Btn is pressed
    // calls the broadcastBtnEvent function on those Btns that 
    // are pressed/released

    public function broadcastBtnEvent(event:BtnEvent, btn:Btn){
        eventSystem.broadcastBtnEvent(event, btn)
    }
}

We’d then have another interface

class BtnEventListener {
    function handleBtnEvent(event:BtnEvent, btn:Btn);
}

And our BtnGraphicSystem would look like

//aspect:<Btn, Graphic>
class BtnGraphicSytem implements BtnEventListener

    public function handleBtnEvent(btnEvent:BtnEvent, btn:Btn) {
        btnGraphicNode = findBtnGraphicNodeForBtnComponent(btn)
        switch(btnEvent){
            case DOWN:
                btnGraphicNode.graphic.frame = 2
            case UP:
                btnGraphicNode.graphic.frame = 1
        }
    }

Our BtnGraphicSystemthen gets registered as a listener for BtnEvents
to the EventSystem. When the BtnSystem broadcasts a BtnEvent, the
EventSystem will propagate that call to the BtnGraphicSystem to handle.

Does this approach make sense?

If it doesn’t: is there a better way?

If it does: how would we implement findBtnGraphicNodeForBtnComponent()?:

Would we always register BtnGraphicNodes within a Btn->BtnGraphicNode map within our BtnGraphicSystem upon registration to be looked up later?


Get this bounty!!!

#StackBounty: #c++ #lua #entity-component How to store Lua script's inner state?

Bounty: 50

Situation:

  • I am working on an Entity-Component system, and I am using LuaBridge as a Lua binder.

  • There is only one Lua State.

  • Currently when I update the game objects, I just check whether it has a script defined or not. If there is, I call luaL_dostring() on it, and I call its update() function.

  • I have a script, where I declare a global variable in its start() (it is called when the script runs for the first time), and increment it at every update() then print it out

Question:

  • I would like to achieve separated inner state saving for my scripts.
    • For example If I add the same script to two different game objects, currently the printed out numbers will be 1,2,3,4,5,6 instead of 1,1,2,2,3,3, etc.
    • This is because they use the same Lua State (correct me if I am wrong)

    • But as I heard it’s not a good practice to have a lua state for every script because If I just have 5 scripts, and I add these to 3 different game objects, there would be already 15 lua states.

How should I achieve my goal?


Get this bounty!!!

#StackBounty: #c++ #lua #entity-component How to store Lua script's inner state?

Bounty: 50

Situation:

  • I am working on an Entity-Component system, and I am using LuaBridge as a Lua binder.

  • There is only one Lua State.

  • Currently when I update the game objects, I just check whether it has a script defined or not. If there is, I call luaL_dostring() on it, and I call its update() function.

  • I have a script, where I declare a global variable in its start() (it is called when the script runs for the first time), and increment it at every update() then print it out

Question:

  • I would like to achieve separated inner state saving for my scripts.
    • For example If I add the same script to two different game objects, currently the printed out numbers will be 1,2,3,4,5,6 instead of 1,1,2,2,3,3, etc.
    • This is because they use the same Lua State (correct me if I am wrong)

    • But as I heard it’s not a good practice to have a lua state for every script because If I just have 5 scripts, and I add these to 3 different game objects, there would be already 15 lua states.

How should I achieve my goal?


Get this bounty!!!