Search Unity

Question How to turn on/off, ISystem update?

Discussion in 'Entity Component System' started by Zimaell, Mar 18, 2023.

  1. Zimaell

    Zimaell

    Joined:
    May 7, 2020
    Posts:
    409
    I am studying the lessons on entities 1.0.0, now I am interested in the question - how to turn on/off, ISystem update?
    Here is the spawn in the example
    Code (CSharp):
    1. partial struct SpawnSystem : ISystem{
    2.     [BurstCompile]
    3.     public void OnCreate(ref SystemState state){
    4.         state.RequireForUpdate<SpawnDataComponent>();
    5.         }
    6.     [BurstCompile]
    7.     public void OnDestroy(ref SystemState state){}
    8.  
    9.     [BurstCompile]
    10.     public void OnUpdate(ref SystemState state){
    11.         var spawnData = SystemAPI.GetSingleton<SpawnDataComponent>();
    12.  
    13.         var ecbSingleton = SystemAPI.GetSingleton<BeginSimulationEntityCommandBufferSystem.Singleton>();
    14.         var ecb = ecbSingleton.CreateCommandBuffer(state.WorldUnmanaged);
    15.         var vehicles = CollectionHelper.CreateNativeArray<Entity>(spawnData.TankCount, Allocator.Temp);
    16.         ecb.Instantiate(spawnData.TankPrefab, vehicles);
    17.  
    18.         state.Enabled = false;
    19.         }
    20.     }
    state.Enabled = false; as I understand it, it disables the update of this system, but what if I need to create a couple of objects in the process? I am changing the data in the SpawnDataComponent and again I need to run one cycle of this system, but how do I do it?

    How do I send a request to the spawner so that it creates something and turns off?
     
    Eristen likes this.
  2. JooleanLogic

    JooleanLogic

    Joined:
    Mar 1, 2018
    Posts:
    447
    The System will run or not based on RequireForUpdate. You shouldn't need/use Enabled for this. The problem is you're requiring for update only a singleton component which is presumably always alive due to it having the prefab reference.

    1. The simplest solution is to require an additional tag or enableable component. I.e.
    state.RequireForUpdate<SpawnDataComponent, SpawnTag>(); // <- Not valid syntax but you get idea
    Then add/enable SpawnTag when you want to spawn again and remove/disable spawnTag after spawning. No need for state.Enabled. This approach allows for a single spawn action per frame.

    2. Alternatively, store the prefabs in a different singleton and spawn SpawnDataComponent entities when you need them. Then destroy those spawner entities after you've instantiated from them. You use EntityQuery for this approach.
    The system will run when said entities are present so no state.Enabled required here either. This approach allows for multiple spawn actions per frame.

    3. You could also re-enable the system from another system but it's a hackneyed solution versus the above data approaches.
    state.WorldUnmanaged.GetExistingSystemState<SpawnSystem>().Enabled = true;
     
    Eristen and Zimaell like this.
  3. jorrit-de-vries

    jorrit-de-vries

    Joined:
    Aug 7, 2009
    Posts:
    71
    Unfortunately state.RequireForUpdate doesn't check the enabled state of an IEnableableComponent (Entities 1.0.0-pre.65). From the docs of SystemState.RequireForUpdate<T>() and SystemState.RequireForUpdate(EntityQuery)

    Note that for components that implement <see cref="T:Unity.Entities.IEnableableComponent"/>
    this method ignores whether the component is enabled or not, it only checks whether it exists.
     
    mvinicius2k and JooleanLogic like this.
  4. lclemens

    lclemens

    Joined:
    Feb 15, 2020
    Posts:
    761
    That statement about IEnableableComponent not working with RequireForUpdate() only occurs in the remarks section for this overload: "public void RequireForUpdate<T>()". So you might think that it would still work under the overload with the query "public void RequireForUpdate(EntityQuery query)". Unfortunately, I can confirm that the query overload not work either. :oops:

    So this will not work as expected...
    state.RequireAnyForUpdate(state.GetEntityQuery(ComponentType.ReadOnly<MyEnableableTag>()));