Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

System not run: What is the logic?

Discussion in 'Entity Component System' started by Jyskal, Oct 16, 2019.

  1. Jyskal

    Jyskal

    Joined:
    Dec 4, 2014
    Posts:
    28
    Hi everyone,

    I ran into the following issue and I am trying to understand why the system is behaving as it is and if there is a way around this.

    I have a custom Render System as follows:

    Code (CSharp):
    1.     protected override void OnUpdate()
    2.     {
    3.       AddCellMeshes();
    4.       RenderMeshes();
    5.     }
    Code (CSharp):
    1.     void AddCellMeshes()
    2.     {
    3.       Entities.ForEach((Entity entity, RenderMesh mesh, ref IsNew isNew, ref MeshData data, ref Position position) => {
    4.           ...
    5.           em.RemoveComponent<IsNew>(entity);
    6.           ...
    7.  
    My RenderMeshes function does not use Entities.ForEach or EntityQuery, it just reads from a Dictionary which has entities stored inside that need to be rendered (since it is a 2D tile game and I need O(1) per tile mesh access).

    Now when I run the code, the System will only run once. After that it will go to "not run" because according to the EntityDebugger, there are no more entities that meet the criteria of the Entities.ForEach which makes sense since I remove the "IsNew" tag. However you would expect subsequent functions to still be executed if they contain no "filter". This is not the case.

    I assume this is done for performance reasons, so that a system is no longer run if there are no Entities around with a matching Archetype. However this creates issues in my case.

    Is there a "correct" way to circumvent this default behavior? I found adding Entities.ForEach((RenderMesh x) => { }); to the RenderMeshes() function will do the trick but it feels kind of hacky and surely will impact performance.
     
  2. BanJaxe

    BanJaxe

    Joined:
    Nov 20, 2017
    Posts:
    47
    You can put the attribute [ExecuteAlways] on the system, then it will run even when no entities match.
     
  3. Jyskal

    Jyskal

    Joined:
    Dec 4, 2014
    Posts:
    28
    Does not work. I still get System not run.
     
  4. sschoener

    sschoener

    Joined:
    Aug 18, 2014
    Posts:
    73
    ExecuteAlways is the wrong attribute. You want AlwaysUpdateSystem.
    • ExecuteAlways is when you want something to run both at runtime and in the editor. Docs.
    • AlwaysUpdateSystem is when you want a system to skip its internal checks as to whether it should get updated. Docs.
     
    addent and florianhanke like this.
  5. BanJaxe

    BanJaxe

    Joined:
    Nov 20, 2017
    Posts:
    47
    Sorry you are right, I had the wrong attribute name.

    Code (CSharp):
    1. [AlwaysUpdateSystem]
    2. public class SystemName : ComponentSystem { ... }
     
    addent likes this.