Handling Events and UI for a turn-based ECS game

Hey everyone, I’m prototyping a grand strategy game to familiarize myself with ECS. At the end of every turn, I want a group of systems to simulate elements of my population. I followed some tutorials and made a system that listens for a button press via tags. Now I’ve come across two issues:

1. Using burst compile gives me an error: "
…\ProtoPopGrowthSystem.cs(13,9): Burst error BC1025: Accessing the type ProtoPopCalTag (e.g. using typeof) is not supported" Is there a way to rectify a UI button press to be more friendly with burst/ECS?

    [BurstCompile]
    public void OnUpdate(ref SystemState state)
    {
        if(query.IsEmptyIgnoreFilter)
            return;
       
        var job = new ProtoPopGrowthJob{};
        job.ScheduleParallel();
       
        state.EntityManager.RemoveComponent<ProtoPopCalTag>(query);
    }
}

2. I’d like to retrieve the total population from my entities and display it on TMP text in world space. I was setting up each entity to have its own canvas and text, but I noticed that the canvases can’t reference a camera outside of the sub-scene (as shown in the image below). Now I’m lost on trying to bridge the entity to UI gap. Any help would be appreciated.

  1. You need to show full code, as the error message does not seem to correlate to the code you have shown.
  2. You have to wire it up at runtime. I think most people just use Camera.main to get the camera. I use a cross-scene GUID solution for connecting subscene entities with scene GameObjects.
1 Like

Thank you.

Here is everything that touches the ProtoPopCalTag:

Population Growth ISystem:

using System.Collections;
using System.Collections.Generic;
using Unity.Burst;
using Unity.Entities;
using UnityEngine;
public partial struct ProtoPopGrowthSystem : ISystem
{
    private EntityQuery query;
  
    [BurstCompile]
    public void OnCreate(ref SystemState state)
    {
        query = state.GetEntityQuery(typeof(ProtoPopCalTag));
    }
  
    [BurstCompile]
    public void OnUpdate(ref SystemState state)
    {
        if(query.IsEmptyIgnoreFilter)
            return;
      
        var job = new ProtoPopGrowthJob{};
        job.ScheduleParallel();
      
        state.EntityManager.RemoveComponent<ProtoPopCalTag>(query);
    }
}

[BurstCompile]
public partial struct ProtoPopGrowthJob : IJobEntity
{
    //Run logic
    public void Execute(ProtoPopAspect protoPopData)
    {
        protoPopData.GrowPopulation();
    }
}

Population Calculate Button and Tag:

public class ProtoPopCalButton : MonoBehaviour
{
    private EntityManager entityManager;
    private EntityQuery query;

    void Start()
    {
        entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
        query = entityManager.CreateEntityQuery(typeof(ProtoPopCalTag));
    }

    public void OnButtonPress()
    {
        Entity entity = entityManager.CreateEntity();
        entityManager.AddComponentData(entity, new ProtoPopCalTag());
    }
}

public struct ProtoPopCalTag : IComponentData { }

I also just changed the ProtoPopCalTag from class to struct, but that didn’t fix anything.

Use QueryBuilder on line 13. The way you are doing it now is not Burst-compatible. Or just remove the [BurstCompile] on OnCreate if you don’t care that much on startup performance.

That solved it! Here’s the new version in case anyone else comes across a similar issue:

    private EntityQuery query;
  
    [BurstCompile]
    public void OnCreate(ref SystemState state)
    {
        query = SystemAPI.QueryBuilder().WithAll<ProtoPopCalTag>().Build();
    }

Also, I am looking at your framework for working with DOTS. Looks amazing. Is your GUID solution contained in that package? This solution sounds like it’ll help with more than just connecting UI.

Indeed it is. https://github.com/Dreaming381/Latios-Framework-Documentation/blob/main/Transforms/Getting%20Started.md#gameobjectentity

1 Like