Review Please

So ive been trying to implement a little experiment using SubScenes and LiveConvertGameView where Im able to change my gameobject and generate some entities and update them with some data while the game is running. Problem is I keep moving 1 step forward then 5 steps back. So ive decided to take out all the complex stuff and just write very simple system to get some feedback to make sure the basice are good. Please leave any comment and dont assume I know anything.

I would also like to know give that im changing my gameObject during runtime where my EntityQuery should sit, currently they are in Update() , is this expensive , can they just be in OnCreate(). Same goes for SetFilterChanged().

Thanks in advance.

using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;
using UnityEngine;


namespace Check.Yourself
{

    //
    //IComponentData
    struct EntityCountComponent : IComponentData
    {
        public int entityCount;
    }

    struct EntityDataComponent : IComponentData
    {
        public int entityData;
    }

    //
    // GameObjectConversionSystem
    public class ConversionSystem : GameObjectConversionSystem
    {

        protected override void OnUpdate()
        {

            this.Entities.ForEach((TestProxy data) =>
            {
                Debug.Log("<b> <size=13> <color=#9DF155>Info : 1 ConversionSystem : Converting Entities.</color> </size> </b>");

                var ePrimary = this.GetPrimaryEntity(data);

                var cData = new EntityCountComponent
                {
                    entityCount = data.numEntities
                };
                this.DstEntityManager.AddComponentData(ePrimary, cData);

            });
        }
    }

    //
    // ComponentSystem used to create Entities
    public class CreateSystem : ComponentSystem
    {

        private EntityQuery qEntityCount;
        private EntityQuery qEntityData;
        private EntityArchetype aEntityData;


        protected override void OnCreate()
        {

            aEntityData = EntityManager.CreateArchetype
            (
                ComponentType.ReadOnly<EntityDataComponent>()
            );


        }

        protected override void OnUpdate()
        {

            qEntityData = GetEntityQuery
            (
                typeof(EntityDataComponent)
            );
  
            qEntityCount = GetEntityQuery
            (
                ComponentType.ReadOnly<EntityCountComponent>()
            );

            qEntityCount.SetFilterChanged(typeof(EntityCountComponent));


            Entities.With(qEntityCount).ForEach((ref EntityCountComponent c) =>
            {

                Debug.Log("<b> <size=13> <color=#9DF155>Info : 2 CreateSystem : Create Entities.</color> </size> </b>");

                EntityManager.DestroyEntity(qEntityData); // NOT VERY HAPPY WHERE THIS IS SITTING

                NativeArray<Entity> e = new NativeArray<Entity>(c.entityCount, Allocator.TempJob);
                EntityManager.CreateEntity(aEntityData, e);

                e.Dispose();

            });
        }
    }

    //
    // JobComponentSystem to update data on Entities
    [UpdateAfter(typeof(CreateSystem))]
    public class UpdateSystem : JobComponentSystem
    {

        private EntityQuery qEntityData;


        [BurstCompile]
        struct SetData : IJobForEachWithEntity<EntityDataComponent>
        {

            public void Execute(Entity entity, int index, ref EntityDataComponent c)
            {
                DebugInfo();

                c.entityData = 11;
            }

            [BurstDiscard]
            private void DebugInfo()
            {
                Debug.Log("<b> <size=13> <color=#9DF155>Info : 3 SetDataSystem : Setting Data .</color> </size> </b>");
            }
        }


        protected override JobHandle OnUpdate(JobHandle inputDeps)
        {

            qEntityData = GetEntityQuery
            (
            typeof(EntityDataComponent)
            );

            qEntityData.SetFilterChanged(typeof(EntityDataComponent));


            inputDeps = new SetData
            {

            }.Schedule(this, inputDeps);

            return inputDeps;
        }
    }
}

Your conversion system looks fine.

GetEntityQuery should just sit in OnCreate. You only need to call it once. As far as I’m aware SetFilterChanged works fine in OnCreate as well, though people seem to commonly use it OnUpdate for some reason.

A more efficient way of doing your Entities.ForEach loop and destroying the entities in your create system is to use a query to destroy, do your look then use the batch destroy operation after.

Entities.With(qEntityCount).ForEach((ref EntityCountComponent c) => { }

EntityManager.DestroyEntities(qEntityCount);

This isn’t a big deal if you have a small entity set but it can be significantly faster if you are frequently doing this.

Apart from that. I’m not exactly sure why you need the CreateSystem. Why not just do this work in the conversion system. Is it because you’re running into issues with live links?

Thanks for the review, Yes I had a lot of trouble with creating in the conversion system, main issue being that if I made a change at run time I would get out of range exceptions in following systems. It seemed to me live like works better syncing existing entities but this could totally be user error

Implementing your suggestion I have some questions. I had a mistake in the destroy, I should be destroying the EntityDataComponent not the EntityCountComponent which is why I had the comment of it feeling wrong to me.

        protected override void OnUpdate()
        {

            Entities.With(qEntityCount).ForEach((ref EntityCountComponent c) =>
            {
                Debug.Log("<b> <size=13> <color=#9DF155>Info : 2 CreateSystem : Create Entities.</color> </size> </b>");

                EntityManager.DestroyEntity(qEntityData); // NOT VERY HAPPY WHERE THIS IS SITTING

                NativeArray<Entity> e = new NativeArray<Entity>(c.entityCount, Allocator.TempJob);
                EntityManager.CreateEntity(aEntityData, e);

                e.Dispose();

            });
        }

Is there a way to query the filter

if ( qEntityCount.SetFilterChanged == true) 
{
EntityManager.DestroyEntity(qEntityData);
}