#Looking for a way for a system to run after all Baker scripts have run.

1 messages · Page 1 of 1 (latest)

covert nimbus
#

I have tried adding a bespoke component and waiting for that baker script to run and add that component. However the problem is that the system will only wait for one baker script to run in this. Anyway to wait for every entities to feature a certain component?


    public partial struct WaitForBakersSystem : ISystem
    {
        public void OnCreate(ref SystemState state)
        {
            var queryDescription = new EntityQueryDesc
            {
                All = new ComponentType[] { typeof(WaitedForComponent) },
                Options = EntityQueryOptions.IncludePrefab | EntityQueryOptions.IncludeDisabledEntities
            };
            EntityQuery query = state.GetEntityQuery(queryDescription);
            state.RequireForUpdate(query);
        }
    }
#

In other words i'm looking for a RequireForUpdate for all entities.

atomic folio
#

I'm a little confused as this is the default behaviour of baking systems

covert nimbus
#

Oh what really? What is a baking system? How do you define one

atomic folio
#

[WorldSystemFilter(WorldSystemFilterFlags.BakingSystem)]

#

just put that on your system

covert nimbus
#

You place that on the struct definition itself or the OnUpdate method? I tried placing it on the above the struct definition and the OnUpdate method isn't being run.

atomic folio
#

struct

covert nimbus
atomic folio
#

you won't be able to break point it unless you open your subscene

#

baking runs in a different process

covert nimbus
#

Hmm ok, I mean my subscene is loaded

atomic folio
#

open != loaded

covert nimbus
#

Ok, I'm not sure its being run anyway because the collection i'm trying to fill here remains empty..

#

ah I need GetSingletonRW

#

How about if I add an OnCreate method in this system will it be run after the entities have finished baking, or with the other systems at the start of the program?

atomic folio
#

baking systems dont execute at runtime

#

only after baking

covert nimbus
#

Don't execute at runtime at all? So only in the Editor?

atomic folio
#

all baking is editor only

covert nimbus
#

crap

atomic folio
#

Bakers are editor only

covert nimbus
#

ok, then I don't know how i'm going to do this. Essentially I want to fill a NativeHashMap with all of the prefab present in the subscene. All of the prefab have a Guid present in a component called AuthoringComponent.

Initially my system waited using RequireForUpdate that the AuthoringComponent was present. But realized that it only waited for one entity to appear.

#

Knowing that a baking system is editor only, I don't think its the way to go, unless you tell me there's a way to make the NativeHashMap that I generate during baking persist until runtime?

#

Maybe entities created inside a baking system will persist even during runtime?

atomic folio
#

it will break in builds

#

(I do have a dynamic hash map in my library though...)

covert nimbus
#

I'm just surprised nobody's solved this problem. I just want to fill a HashMap with Entities, using the original prefab guid. That way I can easily instantiate ECS entity from a monobehaviour.

atomic folio
#

I've convinced most people doing ECS work in monobehaviours is a bad idea 🙃

#

what you're suggesting doesn't work anyway

#

the entity id in an unloaded subscene will change when it's loaded

#

your hashmap would be pointing to the wrong entity

covert nimbus
#

yeah that's why I wanted to build that hashmap at runtime. Didn't know baking occured at edit time

atomic folio
#

so they won't all load at the same time

#

so that's probably the issue with your original system?

#

otherwise i see no reason it wouldn't have worked if all your entities are in the same subscene

#

because what you were doing in your original subscene is technically fine

#

well except if you have an event in there

#

it really shouldn't be an ISystem

#

as you can't burst compile it

#

should just make it a SystemBase

covert nimbus
#

No they were all in the same system. Simply put RequireForUpdate <AuthoringComponent> waits for at least one entity featuring that component. I have a bunch of entities in that subscene with that component.

#

My other idea was this. OnUpdate is called continuously until either there is a AuthoringComponent and it isn't disabled. The only thing that's missing here is that I would've liked a way to communicate when that whole process is done..

Here the onReadyEvent callback is no longer valid...


namespace Cirrus.UnityExtras.ECS
{
    using static Unity.Entities.SystemAPI;

    using Color = UnityEngine.Color;
    using Entity = Unity.Entities.Entity;
    using Guid = Core.Guid;

    public class AuthoringLibraryManagedComponent : IComponentData
    {
        public Action onReadyEvent;
    }

    public struct AuthoringLibraryComponent : IComponentData
    {
        public NativeHashMap<Guid, Entity> entities;
    }

    public partial struct AuthoringLibraryBakingSystem : ISystem
    {
#if CIRRUS_UNITYEXTRAS_ECS_BURST_COMPILE
        [BurstCompile]
#endif
        public void OnCreate(ref SystemState state)
        {
            state.RequireForUpdate<AuthoringComponent>();
            var em = state.EntityManager;
            var entity = em.CreateEntity();
            var library = new AuthoringLibraryComponent();
            library.entities = new NativeHashMap<Guid, Entity>(10, Allocator.Persistent);
            em.AddComponentData(entity, library);
            em.AddComponentData(entity, new AuthoringLibraryManagedComponent());
        }

        public void OnUpdate(ref SystemState state)
        {
//            state.Enabled = false;
            var em = state.EntityManager;
            var managed = SystemAPI.ManagedAPI.GetSingleton<AuthoringLibraryManagedComponent>();
            ref var library = ref SystemAPI.GetSingletonRW<AuthoringLibraryComponent>().ValueRW;
            foreach (var(entry, entity) in SystemAPI.Query<RefRW<AuthoringComponent>>()
                     .WithOptions(EntityQueryOptions.IncludeDisabledEntities | EntityQueryOptions.IncludePrefab)
                     .WithEntityAccess())
            {
                ref readonly var value = ref entry.ValueRO;
                library.entities.Add(value.guid, entity);
                em.SetComponentEnabled<AuthoringComponent>(entity, false);
            }
            managed.onReadyEvent?.Invoke();
        }
    }
}

#

Maybe I should checkout [WorldSystemFilter(WorldSystemFilterFlags.ProcessAfterLoad)] ?

I wonder if this will wait for all entities to be loaded

atomic folio
#

result will probably be no different than just doing requireforupdate

hollow hornet
#

To make your life easier dealing with native collections inside components (collection component), use Latios Framework. It has something called "blackboard entity" to automatically manage the dependency and disposal of these components. A blackboard can be seen as a singleton entity. I heavily utilize the world blackboard for the kind of things you are trying to do as above.

#

Btw, afaik, your code above is usually frowned upon. If you want to fire a signal that says "the ECS initialization systems have been completed, do the Mono works", you should do it a bit differently.

#

For example, when the game is entering the battle mode, I first show a loading screen to cover everything underneath. Under the hood, my ECS systems prepare the necessary data, the map, initial objects, ect. When everything is ready, I signal the loading screen to hide.

#

What I do is adding a tag to the world blackboard entity to signify that an initialization step has been completed.

#

Then I have a SystemBase to query all of these tags on the blackboard entity and fire a signal to the Mono world from the overrided method SystemBase.OnStartRunning