Post by Admin on Jul 16, 2016 4:31:16 GMT
LP @grofit Oct 01 2015 01:01
at what level can you drive systems from "events" in the game?
so an IReactiveSystem is basically a predicate with an action at the end
and I see that you can use matchers, but assuming you wanted to do something more granular like All entities with component person and heatlh changed and health is <= 0
in rx you could do something like myEntity.Where(x => x.hasComponent<Person>()).OnPropertyChanged(x => x.Health).Where(x => x <= 0).Subscribe(doSomeExecution);
I mean you could write your own events for this stuff but then you need the notions of an event aggregator and expose that to a system like SubscribeTo<SomeEvent>(someExecution); and systems seem to be granular points of execution
so is it possible to express this kind of predicate for a system?
LP @grofit Oct 01 2015 01:07
I guess currently you would have a reactive system for Person matchers and in the executors check the property every frame to see if it is <= 0 then do something... HasPersonDiedSystem : IReactiveSystem
However from a purely reactive perspective I would like to know more on how to ONLY execute a system once all conditions are met or an event is raised
Maxim Zaks @mzaks Oct 01 2015 01:35
Hi @grofit
Lots of questions and I guess you answered most of them already your self. So I will concentrate on the last one. Comparison with Rx.
We don't have the same convenience in Entitas as one have in a typical FRP frameworks, because we try to keep things as simple as possible internally in Entitas. A reactive system is a system which runs once per frame (not on every change) and it gets the entities from the group observer which collected entities which where added or removed to a group. The group is build based on the Matcher that you provide in reactive system interface implementation. There is no mechanism implemented in Entitas where you can add custom component property based filter. However you could write it your self if you create a FileteredReactiveSystem which will have a filter closure field which is applied on every execute. Than you could subclass this System and pass in filter closure which would be executed in base Execute method returning just a filtered subset of the entities that you get from the group observer.
FRP frameworks normally don't have to deal with many changes on frame by frame bases. This is why they can provide lots of convenience for filtering, aggregation etc... Dependent on the game you are implementing, it could happen that hundreds of entities are updated on each frame. In this case you would like to be able to profile and see where exactly the time is wasted. I would argue that nested function calls which are typical for FRP code are very hard to profile for performance.
LP @grofit Oct 01 2015 01:37
well ignoring rx specifically what about events?
the only reason i ask is because it seems atm there is no easy way for one system to notify another without setting a var in a state which would be polled
Maxim Zaks @mzaks Oct 01 2015 01:40
for events its the best to represent them as state. So have a component and create an entity with this component. The benefit is also that than you have an easy way of replayability you just have to capture when certain entities where created and recreate them in in replay.
LP @grofit Oct 01 2015 01:41
and again polling is fine, but t is more lets say i wanted to display some effect on an entity being hit
kk
thanks for info
Maxim Zaks @mzaks Oct 01 2015 01:41
by entity you mean a unity game object, which has a collider?
LP @grofit Oct 01 2015 01:42
well I am sure it would have a view which was a game object
but it would just be a logical event
lets say the entity had a component Shooter and it shot at something, it was within a close enough radius to another entity
and it wants to notify other systems that something logical has happened
I mean you could easily do it all in raw C#, I tend to model most of my stuff without a view and just plug that on as an afterthought wherever possible
Maxim Zaks @mzaks Oct 01 2015 01:43
well if it is a shooter you probably want to create a new entity which has a projectile component
LP @grofit Oct 01 2015 01:44
so however the trigger for it all happens, it would lead to <something> needing to tell a system "Hey this is in a state you need to action" be it component var for state or a simple event (Which also shows intent)
yeah yeah ignore the whole projectile and scene stuff
just look at it as a logical interaction
ComponentA attacks ComponentB, component B wants to do some stuff when its hit
now I could have a var which holds HasBeenHit
which multiple services listen for and do stuff
Maxim Zaks @mzaks Oct 01 2015 01:45
Replace var with component and service with reactive system and that is it.
LP @grofit Oct 01 2015 01:45
AH ok
so you express your state via enabled components
InjuredComponent : IComponent then add it on hit in a service
the only issue I can see there is, whos job is it to remove the component
as lets say you have 3 services which all do something when that component is active
how do you know the previous 2 have done their bit before the 3rd one removes it
if that makes sense?
Maxim Zaks @mzaks Oct 01 2015 01:48
well lets say you have an entity which has a shooter component and at some point it gets Injured component.
Now you have an injured shooter. A reactive system says give me all entities which in last tick become injured shooters so I can heal them for example.
LP @grofit Oct 01 2015 01:48
as one of the main benefits I see with ECS as a pattern vs lets say MVC or MVVM is that you can pretty much just keep adding systems as often as you want to handle new concerns
ok but lets say in that example
I have a system which shows some effect InjuredEffectSystem and something to notify other players TeamMemberInjuredNotificationSystem and then some arbitrary DeductInjuryHealthSystem
Maxim Zaks @mzaks Oct 01 2015 01:49
As I mentioned the reactive systems are backed by group observer wich collects the entities. So even if you would remove this component again it will still be collected so all the reactive systems will get this entity. Internally you would have to check if this component is still there.
LP @grofit Oct 01 2015 01:50
now you ideally need to remove the Injure component from the entity after those 3 are done, but I would say its probably the DeductInjureHealthSystem's job to do it
AH
right ok
so the remove would not happen until the next frame?
Maxim Zaks @mzaks Oct 01 2015 01:51
remove from the observers happen after reactive system is executed. It drains the observer.
github.com/sschmid/Entitas-CSharp/blob/develop/Entitas/Entitas/ReactiveSystem.cs#L87
That sad I have to admit that one of the tough problems in ECS is order of systems.
LP @grofit Oct 01 2015 01:56
really sorry had to go afk, and I am off again in a second
but your information is great, I was just wondering how the best way to structure stuff was and express intent to systems
so thanks again, will be back soon I am sure
Maxim Zaks @mzaks Oct 01 2015 01:57
you welcome!
CodePoKE @gjroelofs Oct 01 2015 21:33
@sschmid There have been several mentions on integrating other forms of Matchers and that there's been progress in implementation, however no activity shows on the github repo.
@sschmid Could you upload these changes if they exists? I've been holding off implementing it here as I understood it would be integrated soon :-)
LP @grofit Oct 01 2015 22:58
after looking at the AbstractMatcher it doesnt seem wildly difficult to make some custom ones
as I think this sort of thing would be VERY good for groups
so you could maintain groups of dead entities (in the sense of a game entity not ECS entity), or entities within a given radius etc
again you could just have components for this InRangeOfPlayer with distance var, or ProperDead etc
but if you were to expose this at a matcher level you could then negate the need for custom components to express some of these scenarios
CodePoKE @gjroelofs Oct 01 2015 23:11
Also; is there any ETA on documentation in code?
at what level can you drive systems from "events" in the game?
so an IReactiveSystem is basically a predicate with an action at the end
and I see that you can use matchers, but assuming you wanted to do something more granular like All entities with component person and heatlh changed and health is <= 0
in rx you could do something like myEntity.Where(x => x.hasComponent<Person>()).OnPropertyChanged(x => x.Health).Where(x => x <= 0).Subscribe(doSomeExecution);
I mean you could write your own events for this stuff but then you need the notions of an event aggregator and expose that to a system like SubscribeTo<SomeEvent>(someExecution); and systems seem to be granular points of execution
so is it possible to express this kind of predicate for a system?
LP @grofit Oct 01 2015 01:07
I guess currently you would have a reactive system for Person matchers and in the executors check the property every frame to see if it is <= 0 then do something... HasPersonDiedSystem : IReactiveSystem
However from a purely reactive perspective I would like to know more on how to ONLY execute a system once all conditions are met or an event is raised
Maxim Zaks @mzaks Oct 01 2015 01:35
Hi @grofit
Lots of questions and I guess you answered most of them already your self. So I will concentrate on the last one. Comparison with Rx.
We don't have the same convenience in Entitas as one have in a typical FRP frameworks, because we try to keep things as simple as possible internally in Entitas. A reactive system is a system which runs once per frame (not on every change) and it gets the entities from the group observer which collected entities which where added or removed to a group. The group is build based on the Matcher that you provide in reactive system interface implementation. There is no mechanism implemented in Entitas where you can add custom component property based filter. However you could write it your self if you create a FileteredReactiveSystem which will have a filter closure field which is applied on every execute. Than you could subclass this System and pass in filter closure which would be executed in base Execute method returning just a filtered subset of the entities that you get from the group observer.
FRP frameworks normally don't have to deal with many changes on frame by frame bases. This is why they can provide lots of convenience for filtering, aggregation etc... Dependent on the game you are implementing, it could happen that hundreds of entities are updated on each frame. In this case you would like to be able to profile and see where exactly the time is wasted. I would argue that nested function calls which are typical for FRP code are very hard to profile for performance.
LP @grofit Oct 01 2015 01:37
well ignoring rx specifically what about events?
the only reason i ask is because it seems atm there is no easy way for one system to notify another without setting a var in a state which would be polled
Maxim Zaks @mzaks Oct 01 2015 01:40
for events its the best to represent them as state. So have a component and create an entity with this component. The benefit is also that than you have an easy way of replayability you just have to capture when certain entities where created and recreate them in in replay.
LP @grofit Oct 01 2015 01:41
and again polling is fine, but t is more lets say i wanted to display some effect on an entity being hit
kk
thanks for info
Maxim Zaks @mzaks Oct 01 2015 01:41
by entity you mean a unity game object, which has a collider?
LP @grofit Oct 01 2015 01:42
well I am sure it would have a view which was a game object
but it would just be a logical event
lets say the entity had a component Shooter and it shot at something, it was within a close enough radius to another entity
and it wants to notify other systems that something logical has happened
I mean you could easily do it all in raw C#, I tend to model most of my stuff without a view and just plug that on as an afterthought wherever possible
Maxim Zaks @mzaks Oct 01 2015 01:43
well if it is a shooter you probably want to create a new entity which has a projectile component
LP @grofit Oct 01 2015 01:44
so however the trigger for it all happens, it would lead to <something> needing to tell a system "Hey this is in a state you need to action" be it component var for state or a simple event (Which also shows intent)
yeah yeah ignore the whole projectile and scene stuff
just look at it as a logical interaction
ComponentA attacks ComponentB, component B wants to do some stuff when its hit
now I could have a var which holds HasBeenHit
which multiple services listen for and do stuff
Maxim Zaks @mzaks Oct 01 2015 01:45
Replace var with component and service with reactive system and that is it.
LP @grofit Oct 01 2015 01:45
AH ok
so you express your state via enabled components
InjuredComponent : IComponent then add it on hit in a service
the only issue I can see there is, whos job is it to remove the component
as lets say you have 3 services which all do something when that component is active
how do you know the previous 2 have done their bit before the 3rd one removes it
if that makes sense?
Maxim Zaks @mzaks Oct 01 2015 01:48
well lets say you have an entity which has a shooter component and at some point it gets Injured component.
Now you have an injured shooter. A reactive system says give me all entities which in last tick become injured shooters so I can heal them for example.
LP @grofit Oct 01 2015 01:48
as one of the main benefits I see with ECS as a pattern vs lets say MVC or MVVM is that you can pretty much just keep adding systems as often as you want to handle new concerns
ok but lets say in that example
I have a system which shows some effect InjuredEffectSystem and something to notify other players TeamMemberInjuredNotificationSystem and then some arbitrary DeductInjuryHealthSystem
Maxim Zaks @mzaks Oct 01 2015 01:49
As I mentioned the reactive systems are backed by group observer wich collects the entities. So even if you would remove this component again it will still be collected so all the reactive systems will get this entity. Internally you would have to check if this component is still there.
LP @grofit Oct 01 2015 01:50
now you ideally need to remove the Injure component from the entity after those 3 are done, but I would say its probably the DeductInjureHealthSystem's job to do it
AH
right ok
so the remove would not happen until the next frame?
Maxim Zaks @mzaks Oct 01 2015 01:51
remove from the observers happen after reactive system is executed. It drains the observer.
github.com/sschmid/Entitas-CSharp/blob/develop/Entitas/Entitas/ReactiveSystem.cs#L87
That sad I have to admit that one of the tough problems in ECS is order of systems.
LP @grofit Oct 01 2015 01:56
really sorry had to go afk, and I am off again in a second
but your information is great, I was just wondering how the best way to structure stuff was and express intent to systems
so thanks again, will be back soon I am sure
Maxim Zaks @mzaks Oct 01 2015 01:57
you welcome!
CodePoKE @gjroelofs Oct 01 2015 21:33
@sschmid There have been several mentions on integrating other forms of Matchers and that there's been progress in implementation, however no activity shows on the github repo.
@sschmid Could you upload these changes if they exists? I've been holding off implementing it here as I understood it would be integrated soon :-)
LP @grofit Oct 01 2015 22:58
after looking at the AbstractMatcher it doesnt seem wildly difficult to make some custom ones
as I think this sort of thing would be VERY good for groups
so you could maintain groups of dead entities (in the sense of a game entity not ECS entity), or entities within a given radius etc
again you could just have components for this InRangeOfPlayer with distance var, or ProperDead etc
but if you were to expose this at a matcher level you could then negate the need for custom components to express some of these scenarios
CodePoKE @gjroelofs Oct 01 2015 23:11
Also; is there any ETA on documentation in code?