Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Need help with ECS understanding.

Discussion in 'Entity Component System' started by mr-gmg, Jan 17, 2020.

  1. mr-gmg

    mr-gmg

    Joined:
    Aug 31, 2015
    Posts:
    62
    Hello guys, I try to shift my mind to start using ECS. I have a simple schema Screenshot_5.png
    And to be honest, I don't know how to implement this using ECS. I understand how systems work, and how to create, move, rotate, chasing objects, for example. But don't understand how to organize something like this. So, please, give me a vector on how to organize this properly.
     
  2. colin_young

    colin_young

    Joined:
    Jun 1, 2017
    Posts:
    243
    It's a bit difficult to give much specific advice without knowing more about what exactly your diagram represents, but I'll make a few assumptions and take a crack at it.

    Assuming each box is an object, therefore data and behavior. What you're going to do with ECS is split the data and behaviors apart. As a guess, your player will have component data attached to it:
    • Player data
    • Human player tag | AI player tag
    • Money data
    And you will probably have some Captain entities with component data attached:
    • Captain data (buffer)
    • Ship data (buffer)
    • Module data (buffer)
    You'll notice that I've done away with the hierarchy. There's really no need for it.

    Now you "simply" write systems that process each type of data, or combinations of component data. e.g. a Move Captain system that processes all entities that have Captain component data. If e.g. you need money to move, your player system would process all entities with both player and money component data.

    The trick is you are processing all of the entities that have the same component data at once, rather than processing a single entity at a time. So each system needs to be independent, although you can control things so that one system needs to run before another. e.g. process the player inputs first to set up the data for the movement.

    Does that kind of sort of make sense?
     
    mr-gmg likes this.
  3. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    Usually it start with determining the hottest/most common code path of your game. A solution will then follow. Because data oriented you will plan the shape of data for machine to work the fastest in that case.
     
    SisyphusStudio and mr-gmg like this.
  4. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    988
    Hello,

    Here is my point of view.
    First not everything make sense to solve with DOTS and ECS.

    I asusme from your diagram that you are trying to do some sort a space RTS where your player can select several units. Your units realy are the captains as I understood the ships are not represented on screen. and the fight is more turn based tahnt realtime laser shooting with hit and miss targets.

    So, IMO, player could be a classic game object that take care of registering player input.
    Captains are entities that have a ship buffer element, a local to world, the rendering compnents, maybe acollider.
    When selecting captain, the corresponding netity is added to a list in hte player game object, and when registering the target position you want your captains to move you add/set a targetposition componnent on each captain selected by the player game object.

    Ship would just be some description of attack, defense, health or something in the same lines and when two captains fight, based on your logic some ships may be destroyed weakening the captains fleet.

    For money either you win some for each ship destroyed in wich case a money compoennt should be added to each ship and added to the player's game object money when a ship is destoyed, or the same thing but with money on hte captain.
    Or even simpler, jsut a fixed amount on each ship destruction so no need for money data on the ships.

    Not clear on what modules for ship are, maybe some sort of special effect like damage relfection or explosion damage on destruction. This is all very dependent on the type of game you are doing and the combat type you are planing.

    In conclusion, start listing all the data you need for each of your entites/game object/game concept/units (call them as you wish). then based on this list of data, pick the one that are the most common in your game (shared by most entities/concept and most present in numbers), these are the one worth managing with ECS. For the rest stick with classi OOP/Monobehavior. Once your are more familiar with the "ECS way of thinking" you can try to "migrate" the rest to it.
     
    protopop and mr-gmg like this.
  5. mr-gmg

    mr-gmg

    Joined:
    Aug 31, 2015
    Posts:
    62
    Guys, thank you for your answers, it helps a lot. I will post the final diagram that I come up with using ECS.
    For now, I have a little question.
    Screenshot_116.png
    Each captain can earn and spend his player's money, and now, I think to store the player's entity in CaptainBufferElement.
    Screenshot_117.png
    In this case, when the captain wants to change the money amount it can take his player's entity and put AddMoneyComponent to it. And the money system can handle it. But I'm not sure if it is a good practice to store entities inside of IComponentData and IBufferElementData. And maybe I can use a more suitable approach for it?

    update: and for this case, I don't need to add CaptainsBuffer to the player's entity, because captains will have the player's entity, and it will be enough. but still not sure that it is good for the ECS approach.
     
    Last edited: Jan 18, 2020
  6. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    988
    What will your captains spend the money on ?
    Additional ships for their fleet ?

    Is there a point in making the captain manage their own money ?
    Can't they just spend the "player's" money directly ?

    Making a captain "carry" his money may be needed if you plan on doing an economy system where the captain need to be physicaly/spatially near a shop to spend it or transfer it to another captain.
    Or if your want each captain to be able to only spend the money they personnaly earned.
    Or you want each captain to earn there own money and the player getting an X% cut taht can be used by any captain.

    Depending on what you want to implement, you may have no other choice but to use entity reference in components.
    It's not inherently bad,but in my experience when I end up using that, it leads to the use of entity command buffer (ECB) in the systems and that leads to a single threaded job that need to complete before the rest of the logic, so having lots of those may hurt performence, that why Unity recommend using the entity command buffer as rarely as possible.

    There are ways to avoid the use of the ECB like setting the data through the use of ComponentDataArray but you need to be aware of thread safety issue that may occur when setting data on entities that are not direct "target" of your system's query.

    EDIT : reference to the doc about use of ECB :
    https://docs.unity3d.com/Packages/c...Unity.Entities.EntityCommandBufferSystem.html
     
    Last edited: Jan 19, 2020
    mr-gmg likes this.
  7. BackgroundMover

    BackgroundMover

    Joined:
    May 9, 2015
    Posts:
    215
    The way I read it was the Captain has an entity reference to its Player, whereby they add the AddMoney component. I don't like this approach as you can only have one AddMoney component on an entity at a time. I can imagine the first frame of a game, all the Captains will want to upgrade themselves, but only the first one will be allowed to put an AddMoney component onto its Player
     
    mr-gmg likes this.
  8. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    988
    If the money is on the player and the addmoney is just a signal to change the player's poney amount then making the addmoney an ibufferelement would solve the issue.
     
    mr-gmg likes this.
  9. BackgroundMover

    BackgroundMover

    Joined:
    May 9, 2015
    Posts:
    215
    I agree, but it feels like its creeping back into OOP territory. The Player gets a buffer of its captains, now a buffer of money additions..

    I agree, having the relationship expressed in two different places would have been bad. A Captain could think it belongs to Player3 because thats the player entity it points to, but Player1 could think it owns the captain because its mistakenly in its Buffer..
     
    mr-gmg likes this.
  10. mr-gmg

    mr-gmg

    Joined:
    Aug 31, 2015
    Posts:
    62
    Thank you for the reply

    Only a player has a money component. And I want to let the player's captains change the player's Money component data.

    a player has money, captains may change this money amount, so they have to be able to affect the money amount somehow. the only way that I came up with, it is to add the player's entity to the captain's component and add AddMoney component to the player, when I need it. But I don't really like this way.

    So, how would you implement this?

    update: I will read more about ComponentDataArray. I still feel like I work wrong with ECS.
     
    Last edited: Jan 20, 2020
  11. mr-gmg

    mr-gmg

    Joined:
    Aug 31, 2015
    Posts:
    62
    Do you mean something like this?
    Code (CSharp):
    1. public struct Player : IComponentData {
    2.     public DynamicBuffer<AddMoney> addMonies;
    3. }
    4.  
    5. public struct Money : IComponentData {
    6.     public float value;
    7. }
    8.  
    9. public struct AddMoney : IBufferElementData {
    10.     public float value;
    11. }
    12.  
    13. public struct Captain : IComponentData {
    14.     public Entity player;
    15. }
     
  12. mr-gmg

    mr-gmg

    Joined:
    Aug 31, 2015
    Posts:
    62
    So, how would you implement this following ECS territory?
     
  13. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    988
    There is no need (I don't even think you can) add the dynamic buffer inside an icompnentdata.

    There a several ways to implement this. And yes it feels like creeping back in OOP territory wich is why I said in my first post that not every thing qhould be solve with DOTS.

    So we have :
    A player that has money and controls captains
    Each captain can earn or spend money (chance the player money data)

    For the player's money a simple Money (IComponentData) on a player entity should be enougth.
    The complexity comes with the relationship between the captain and the player. We have two relationships one is control and one is earning/spending money.

    For the first relationship it is easier to have a ControledEntites (IBufferElement) on the player entity that contains a reference to all the Captain entities that are controled by the player.
    Then you can add an PlayerInput (IComponentData) to the player and read it in a system that sets each captains movement or target or whatever. (note that I ignore the selection logic and assume the player always control all the captains at once for simplicity reasons)

    For the earn/spend money relationship it's trickier. The money change on the player but the interaction that lead to that change is triggered by the captains.
    The game needs a way to tell this captain owned by this player earned/spent money. Let's ignore the other part of the transaction for now (other unit destroyed or what was bought) again for simplicity reasons.

    What you could do is add a MoneyChange (IBufferElement) on the player entity. Add a OwnedBy (IComponentData) on each captain to reference the player entity.
    Then a system could add a MoneyChange element to the player referenced by the OwnedBy component data. Then another system process all the elements in the buffer and update the player's amount before removing the element from the buffer.

    That's it for one possible implementation. It may not be the simplest one, it may not be the most performent one but it's one that should work.

    This implementation does have the bidirectional relationship between player and captain. So there is the possibility for mistake like said vestigal. Without going intondetaios, it's a tradeoff between simplicity of use, mermory performance and cpu performance.


    As a side note I think you should be carrefull of your namings. For me AddMoney implies that it will increase the amount of money the player has, you don't want to create a spend money component for the spend operation. ChangeMoney is more neutral and can be used in both ways (addition and subtraction) without being biased by the name.
     
    mr-gmg likes this.
  14. mr-gmg

    mr-gmg

    Joined:
    Aug 31, 2015
    Posts:
    62
    oh, yes, you right about dynamic buffer, I had to put on the player entity directly.

    At first, thanks a lot for your time and detailed descriptions, this way of implementation seems clear for me
    About naming I completely agree, also think to call it ChangeMoney, for AddMoney I assumed negative changes also.
    So, now it's getting more clear for me and I definitely will implement it like this for now. But maybe someone else knows another way to do it?
     
  15. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    988
    Glad i could help :)
    Let us know how it turned out for you, couole of screenshot or a video maybe ;)
     
    mr-gmg likes this.
  16. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194
    Would developing a prototype in OOP Mono be faster and could you then analyse the method calls and data passing to create a set of systems?

    Potential benefits are you can probably develop this faster and more agilely than using DOTS and if the 80/20 optimisation rule applies (only 20% of your code will be called enough to need optimisation and only profiling will find it) then you would only need to move 20% of your code over to DOTS.
     
    mr-gmg likes this.
  17. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194


    Can I just say that you need to provide the data that makes up the items here as well as an outline of the things they can do to even start to break things down into systems and entities.

    A diagram more like this would be ideal:


    What data and actions does a Player have, or a Captain or a Ship or a Module?

    Does a captain live on a ship as well as direct ships?
    What happens when your captains ship is sunk and what happens to their funds?
    Shouldn't there be other ranks lower than a captain in charge of other ships?
    What is the money used for?
    What can a Player get their Captains to do, what can Captains get their Ships to do and what do modules do for ships?

    What about fuel, ammo, crew, supplies, water, air (space ships?)?

    Can't a simple flat ID system and Owner ID tag create any hierarchy of entities you need?
     
  18. charleshendry

    charleshendry

    Joined:
    Jan 7, 2018
    Posts:
    95
    In my setup I have many different Entities that can earn and use money. I use ChangeMoney as an event Entity. It contains the money value, it could have a bool to determine add/remove (or negative values for remove) and an Entity reference to the Player Entity. Then there's a ChangeMoneySystem that runs whenever these components appear, makes the modifications and then destroys all Entities in the EntityQuery.

    Depending on how many Captain Entities you have, it may be efficient to make the PlayerID reference an ISharedComponent. That way when you want all the associated Captain Entities, you get the Player ID and use it as a shared component filter. This gives you an EntityQuery of the associated Captain Entities without the need for DynamicBuffers or iterating through all Entities.
     
    mr-gmg likes this.
  19. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    988
    Hi, I did consider the entity event "patern" my issue is that then your eventventities can be run in a multithreaded context because you can't garanties that no two ChangeMoney event entities will act on the same player money.

    With dynamic buffer you can at least process several player in parrallel.

    Does the shared component you talk about solve that issue? If so I would be interested in and exemple implementation:)
     
    mr-gmg likes this.
  20. charleshendry

    charleshendry

    Joined:
    Jan 7, 2018
    Posts:
    95
    Ah yes, hadn't considered parallel access to the same Entity.

    No, the shared component is not related to the ChangeMoney aspect. It's an alternative for your parent child hierarchy.
     
    mr-gmg likes this.
  21. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    988
    I think he is just trying to figure out how to use dots. You may be overcomplicating things I think he should just focus first on few very simple systems like making a captain/ship move.
    This alone bring lots of questions, how do you register player input, how do you transform these inputs in movement on an entity, how do the player select the entities he want to move.

    Design is important, but, especially when dealing with unknow technology, there is such a thing as over designing. You may have come up with the perfect design but once you write your first line of code you figure out it's all wrong because the technology doesn't work at all like you thought it would.
    Doing a full OOP design diagram will box you in that thinking and it will be very dificult to get out of your habits.

    IMO you are much better off thinking of very little interractions.
    Movement what do I need for that, something to move (translation or localtoworld), a direction toward wich to move (float3 or float2), the speed of the movement (float). There you go your first building blocks for your first system. Once stuff moves, you can add something else, like ok it move but how to I (the player) set the direction I want it to move, boom you need an input system. Then, ok now I have several ships, how to tell which to move... Guess I need some sort of selection system.

    I think it's much better to implement things incrementally, and DOTS is well fit for that once you have a system working with that method, the single responsibility principle is enforced and if you want to change something like switch to phisics based movement it's easy to do.
     
    mr-gmg likes this.
  22. mr-gmg

    mr-gmg

    Joined:
    Aug 31, 2015
    Posts:
    62
    Thank you for the answer, please, tell me, what do you mean by flat id system and owner tag?
     
  23. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194
    Often with hierarchies you end up hard coding relationships with references to other entities. However if you look at databases or a more data driven approach would be to use ID's and Owner ID fields to link sets of data.

    (+) Benefits your have a more flexible data driven ownership system. For instance a Module could have multiple owners e.g. ship/captain/player or game development specific owners e.g. Map might own entities it displays.​

    (-) Cons you have to search and filter data to transfer information from/to owners/owned entities as opposed to a direct reference to the owner or owned item.
    Note you might be able to get around the searching for an ID if it matches an array index for the entity.
     
    Last edited: Jan 21, 2020
    mr-gmg likes this.
  24. RandyBuchholz

    RandyBuchholz

    Joined:
    Sep 23, 2016
    Posts:
    51
    Another way to look at that is that the better a technology supports design, the easier it is to work with. Doing detailed design work early on helps uncover holes in technologies. It also helps develop standard approaches. I feel a missing part of the whole ECS effort right now is approaches to modeling ECS systems. A standard approach to modeling ECS would provide a framework for advancing the technologies. While ECS is "data oriented" at one level, at the design level it's more "type oriented" - an entity definition (i.e., Archetype) is a collection of type abstractions (not type instances). Using standard OO modeling techniques doesn't work. I've been doing Process, OO, & Data Modeling for over 20 years, and none of them really support ECS well. SOA model types like BPEL are showing some of the best results for me when coupled to OO models incorporating heavy use of inner classifiers. I'm able to generate some (semi) decent code from the models.
     
    kevdome3000 likes this.
  25. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    988
    The conversion workflow work reamly well for me. I use the auto generate anotation and the have a requierement based workflow allowing me to build the archetypes I need to perform an operation in a system. Then adding these requierement based component allow me to think of the gamendesign in a much more familiar way.
     
  26. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194
    Really if it lets you break the problem domain into a set of objects, methods and data, things we humans do naturally then analyse the data paths and processes to create systems.

    Take this card game OOP Design, I would say that it follows the concepts of the problem domain well and should be a good starting point (it captures a lot of the data and processes needed) for creating systems which IMHO are often the method calls we use in OOP.

     
  27. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    988
    Yes but agin, it might box you in a way of thinking.
    Take the hand for exemple. do you need an entity that represent that hand ?? Do you even need to have arrays ?
    Can you not just get away with Cards and Player entities, and have card reference a player entity (so they are in it's hand) or not (in the deck). Instead of shuffling the deck, maybe you can just take one card entity randomly in the card entities that don't have a player reference and assign them one.

    Again, I'm trying to force myself to think out of the OOP box. It may not be a good option and again some things don't need to be ECS...
     
  28. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194
    A lot of OOP structure is ownership, with a flat owner ID and owned by ID tag you can assign cards to a player's hand or the dealers deck or any other position in the game e.g. discards/in play/wild card. Or even allow multiple owners e.g. the funds in the pot could maintain their original owners if the game if forfeit or cancelled.

    So other than the fact that hands for different games can have different number of cards unless you want to implement card games where players have multiple hands of cards.

    So maybe we just need Player / Dealer / Card / Game entities, although would the game be a subset of systems for that game type?

    And what about the betting in the game shouldn't there be a winners pot?

    So if you view OOD as a way to break a problem down that provides you with all the data and processes within the domain you can then remove the Objects and build up systems and entities to make a DOTS solution in theory.
     
  29. RandyBuchholz

    RandyBuchholz

    Joined:
    Sep 23, 2016
    Posts:
    51
    Exactly. A trap that gets me from OO thinking is the idea of collections and "hard relationships" in general. It helped me to switch my thinking to the idea that things can't "have" collections, but they can have related tag definitions that can be applied to "children". Why I think OO models don't work real well is that they tend to define hard/static relationships. ECS is more about fluid dependencies.

    For the card game I just see three components - Player, Bet, and Card. And they can be grouped or moved through states with tags.
    upload_2020-1-23_14-59-22.png

    A Player has chips, and a position at the table so we can track who gets cards first, deals, bets first etc. A "single" PlaysFirst tag moves through the table order on each hand.
    A Card has two manifestations - the deck and wild-cards. Cards in the deck move from the deck to player hand to discard by being tagged with mutually exclusive tags. The Wild cards are a set with a Shown tag. Shown is on the archetype for all cards. At the end of a hand, all cards in hands that haven't folded are set to be shown.
    A Bet has two states - when a bet is placed an entity is created and tagged with Player and tagged Active. Bets are Active when they can be called. Once all bets and calls are settled the active tag is removed and a Pot tag is added. It's not necessary to aggregate into a pot total, a job can get the total. At the end of a hand they are aggregated into Player.Chips and destroyed.

    Everything else is jobs/systems.

    The jobs are defined with process decomposition. Starting at the top. Each flow represents a job producing a new or modified "data" entity, or a "control entity". Control entities are read & destroy used only to trigger job execution.
    upload_2020-1-23_15-1-26.png

    eventually getting down to the resource flow for individual jobs that map back to entities.

    upload_2020-1-23_15-3-35.png

    A top-level model that keeps things together is kind of cryptic. All the "extra" stuff makes the model a valid OO model, and important for code generation.

    upload_2020-1-23_15-5-9.png
     
    WAYNGames likes this.
  30. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    988
    Yes, a lot of things in the card game an be thought of states.

    May be in this case a ISharedComponentData could be used for the state, ensuring mutual exclusivity, efficient storage and processing. The state don't actually have data so having it as an ISharedComponentData don't relly mater as long as we can filter on it for certain jobs.
     
    Last edited: Jan 24, 2020
  31. RandyBuchholz

    RandyBuchholz

    Joined:
    Sep 23, 2016
    Posts:
    51
    Have you thought about an escrow/transaction approach? Sometimes adding an association container can simplify relationships. Instead of buffers in memory you can place the funds in an "escrow" entity in one job, and in another job you can complete the transaction and destroy the escrow. If there is a issue you can roll back the transaction - return the money to the originator. Taking it a step farther, you could move financials into Account entities. A captain doesn't need to know about the accounts directly (i.e., manage a collection) or have a money component. I think a (shared?) component with an ID for captain/player could be created and applied to ships, accounts, etc. to define ownership. You abstract out the relationship between two types (Player/Captain) and just have (Account/Account). A transaction entity could be created with two account numbers (to, from) and an "owning account". When the transaction is created it is owned by the from, when it is in process it has no owner (or assign an escrow account). When the transaction is completed set the owner to the "to". You can add the money to the account and delete the transfer, or keep the transfer to have a ledger of transactions.
     
    mr-gmg likes this.
  32. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    I have not read everything throughly but I can provide additional example why you need to state the work you want to do with data to be able to choose a suitable API from the lib.

    Your diagram present the design in OO, which is understandable since the design is made for human. Things appears to be in other things in hierarchy. There are many equivalent concept of in in ECS which may get you the same OO abstraction in your mind :

    - They stay in the same chunk because of the same archetype.
    - Components attached to the same entity, if you view some of your thing as components.
    - They have the same SCD value (which again locks them in the same chunk), e.g. should you treat Player as shared data.
    - They remember Entity field of each other back and forth, making them know each other and could go with random access, to prevent the design getting in the way of data layout.
    - They are in the same dynamic buffer of Entity stored somewhere else (same style as linked entities produced from conversion workflow, where child game objects are represented that way)

    This may lead you to think that so many things need to be attached to the player entity (by attaching components, or by remembering Entity in some of the field) since it is at the root of your graph. And you get question like should Ship be IComponentData that attach to captain entity, or ship is a new entity with Ship IComponentData, and how would that relate to captain.

    But actually I think you should choose the correct technology that benefits the work on data. (not only benefit your understanding, though you can balance it) For example you mentioned captain should looks like the first ship in the list. The only choice for ships is now dynamic buffer of entities because otherwise order queried is not guaranteed. But if you know the weakness of working with dynamic buffer like : you cannot just destroy ship entities now and you have to also maintain the dynamic buffer on the captain (and you think you want to easily destroy ships), when you use command buffer with dynamic buffers SetBuffer clean up everything and have you start over, etc. Then you may not want dynamic buffer solution just so you could get a "first in the list". Maybe each ship could just have a SCD with a single Entity of their captain. Then you could use SCD filter to get all ships of a particular captain and iterate to find out the first, or destroy all ships quickly, etc. it is always depending on the work you planned.

    Modules looks like a component that should be on Ship. But from data standpoint it is helpful to realize that if some ship do not have Module2 then they get to a separated chunks (bad : waste space, good : may improve parallel jobs). And each component comes in linear memory when queried, so that benefits performance. If you name the module in human language like GunModule with many things about the gun inside, but the actual hot work is mostly iterating through guns to render them and you need just an enum of type and its color in the middle of the GunModule struct, maybe you want Appearance component on each ship instead so you can get just that part. (and stop calling them module since Appearance doesn't sounds like a module)

    Also you may not choose a solution based on protection like in OO. For example if you want the player's money to only be modifiable by captain that player own, in OO you can make it safe with language features that it looks like captain is decreasing the money he is able to. But in ECS everything are done with the EntityManager and there is no protection. So captain do not perform work because it is also data. It is always EntityManager that perform work. Some remaining protection in ECS includes `internal` type that library designer locked, then you cannot add or remove that type but still nothing prevent you to query by other means and destroy entities, etc. So maybe don't think much about safeguarding the code from programming error as nothing could prevent EntityManager from doing something.
     
    Last edited: Jan 24, 2020
    mr-gmg likes this.
  33. mr-gmg

    mr-gmg

    Joined:
    Aug 31, 2015
    Posts:
    62
    Thanks all you guys, it was very helpful! I'll share the final scheme that I come up with.