#Live Converted Entities Disappear / Buffer Empty

1 messages · Page 1 of 1 (latest)

quaint hound
#

(demo video coming next)

I have a Baking scene, that registers a few prefabs. Only Object on there has this Authoring Component:

namespace Jovian.Authoring
{
    public class ShipRegistryAuthoring : MonoBehaviour
    {
        public GameObject[] ships;
    }

    public class ShipRegistryBaker : Baker<ShipRegistryAuthoring>
    {
        public override void Bake(ShipRegistryAuthoring authoring)
        {
            var self = GetEntity(authoring, TransformUsageFlags.None);
            var buffer = AddBuffer<ShipPrefabRegistryElement>(self);
            
            foreach (var ship in authoring.ships)
            {
                RegisterPrefabForBaking(ship);
                var prefab = GetEntity(ship, TransformUsageFlags.None);
                buffer.Add(new ShipPrefabRegistryElement {prefab = prefab});
            }
        }
    }

    [Serializable]
    public struct ShipPrefabRegistryElement : IBufferElementData
    {
        public Entity prefab;
    }
}

It works well when the scene is closed, but if the subscene is open, the objects disappear and the ShipRegistry object doesn't work (I think its buff is empty, but also all entities that were spawned from the prefabs previously in it at runtime disappear)

#
    [RequireMatchingQueriesForUpdate]
    [UpdateInGroup(typeof(InitializationSystemGroup))]
    [StructLayout(LayoutKind.Auto)]
    public partial struct VesselSpawningSystem : ISystem
    {
        private const int VesselsToSpawn = 50;

        private EntityQuery _requests;

        private EntityCommandBuffer GetEntityCommandBuffer(ref SystemState state)
        {
            var ecbs = SystemAPI.GetSingleton<BeginSimulationEntityCommandBufferSystem.Singleton>();
            var ecb = ecbs.CreateCommandBuffer(state.WorldUnmanaged);
            return ecb;
        }

        public void OnCreate(ref SystemState state)
        {
            state.RequireForUpdate<BeginSimulationEntityCommandBufferSystem.Singleton>();
            _requests = state.EntityManager.CreateEntityQuery(typeof(TagRequestSpawn));
            state.RequireForUpdate<ShipPrefabRegistryElement>();
            state.RequireForUpdate<TagRequestSpawn>();
        }

        public void OnDestroy(ref SystemState state)
        {
            _requests.Dispose();
        }

        public void OnUpdate(ref SystemState state)
        {
            var rolling = 0;
            var ecb = GetEntityCommandBuffer(ref state);

            var registry = SystemAPI.GetSingletonBuffer<ShipPrefabRegistryElement>();
            foreach (var bubble in SystemAPI.Query<Bubble>().WithAll<TagRequestSpawn>())
            {
                for (var i = 0; i < VesselsToSpawn; i++)
                {
                    var ship = ecb.Instantiate(registry[rolling++ % registry.Length].prefab);

                    var transform = LocalTransform.FromPositionRotation(
                        Random.onUnitSphere * 100,
                        quaternion.identity);
                    ecb.SetComponent(ship, transform);

                    //Important, so freshly spawned ships do not leak into the void world (or are rendered)
                    ecb.RemoveComponent<PhysicsWorldIndex>(ship);
                    ecb.AddComponent(ship, new ReqBubbleEntry() {root = bubble.root, group = bubble.groupIndex});
                    ecb.AddComponent<TagColliderBootstrap>(ship);
                }
            }

            Log.Info($"Spawned {rolling} ships");

            //clear all spawn requests (even ones we couldn't handle
            ecb.RemoveComponent<TagRequestSpawn>(_requests, EntityQueryCaptureMode.AtRecord);
        }
    }
#

Since the spawning system seems to act at two different points in time based on whether the Subscene is open or closed, I wonder if I am doing something wrong here.

#

Edit Mode Difference; seems like the 2 prefabs are being baked into the scene (even though just the registry object has the buffer, but I guess they need to live somewhere)

#

Play Mode Difference:

#

(hundreds of entities, as spawned) - but when subscene is opened for live edits during runtime, all disappear.

#

But the Ship Registry exists and the Buffer isn't empty.

marsh shoal
#

So how do the Bubble and TagRequestSpawn components work? They're the things that are presumably actually being an issue

quaint hound
#

Entities with the Bubble SCD can have TagRequestSpawn to get 50 ships spawned in.

These entities exist, they are loaded from another subscene (and they stay intact when that switches to live edit - but they are not prefabs)

#

Only 2 such entities loaded in the example video thus 100 ships spawned.

#

TagRequestSpawn is just a tag.

I'll check why the 0 ships spawned message comes up before the bubble portal "errors". (these are unrelated, and none of those wants to spawn anything, and actually the Bubble component is never given to these erroring entities for lack of data - just a lookup fail, I can remove all entities except for the two that spawn)

#

What makes you think these are at fault?

marsh shoal
#

Because the only way for you to get a message that says 0 ships spawned is if your query had no matches

#

the ship prefabs could be registering just fine, they presumably are, there's nothing to show that they're the issue

quaint hound
#

(I had loglevel too high, changed it to a warning - yes, the spawn system runs before the bubbles are there)

Why does that cause the existing entities to despawn though?

#

Super weird, why does the SpawningSystem run, nothing has a TagRequestSpawn at that time.

marsh shoal
#

that I am not sure about, I'm not familiar with opening and closing subscenes and what happens to things when you do that (I would presume a rebake would be triggered but 🤷, I don't screw with it), someone else would have to chime in there

quaint hound
#

Ok, semi solved.

#

Thanks for pointing this out, I will look for the actual explanation but the Cause was that the system, indeed, was processing the TagRequestSpawns before there were bubbles.

And I got it, I changed it so the entities to become bubbles were BAKED with the TagRequestSpawn (but didn't have the SCD yet, which is a runtime-only thing).

#

Ok, mostly got it now, thanks Vertx.

#

The [RequireMatchingQueriesForUpdate] I used to have there did nothing. When I built the new baking, I added a RequireForUpdate for TagRequestSpawn, and inadvertently undid the fix again by not baking the SCD with the entity, and not having that on the System.

Cool, cool.

#

You just need people who ask the right questions. 🙂

#

Still can't switch between live edit and normal play mode, but the base improvement is tremendous.

marsh shoal
#

Yeah I hate RequireMatchingQueriesForUpdate, I'm kinda not trusting it, I feel like some parts of the API say "if any query matches the system will run" and other parts say things are required, and I have no idea what takes precedence or how to be specific about it. And I think all sorts of uses of SystemAPI start counting as queries, and I don't fully understand which ones are actually generating required or optional matches.
I'd love clarification on it all but I've been putting it off as my project is in very early days and it doesn't matter much for it.

terse sapphire
#

in a bursted isystem, it's also extremely cheap to just say if (your specific condition) return; at the top of your OnUpdate. i think if we were to start over today, RequireMatchingQueriesForUpdate would not exist

quaint hound
limpid sky
#

I could be wrong, but I think if you look at the generated code you can see how it's done e.g. if (!__query_1839929615_0.IsEmptyIgnoreFilter) {

So presumably if you don't use RequireMatchingQueriesForUpdate then alternatively you'd construct your queries in OnCreate and check for IsEmptyIgnoreFilter yourself in OnUpdate?

quaint hound
#

IsEmptyIgnoreFilter implies there's also a non-filter-ignoring variant? That could be very useful.

limpid cradle
#

IsEmpty