#How to spawn entities when scene starts?

1 messages · Page 1 of 1 (latest)

rocky rapids
#

How to spawn entities from prefabs or runtime-generated meshes(verts/tris/uvs) when scene starts?

rocky rapids
#

this example only shows OnUpdate()

#

but i only need to spawn a thing single time

#

OnCreate or with smth else

soft stag
#

well, what stops you from doing NextSpawnTime the time that will never be there?

#

or using bool to disable whole thing

#

or just destroying entity that holds component for spawn

rocky rapids
#

idk asking if there is some generally good approach to spawn hundred entities and forget about everything

outer light
#

Hey! All the examples shows that we want to do it inside the OnUpdate and just set the "state.Enabled = false; " to create a system that just runs once. Here is how I do it in my project:

    {
        state.Enabled = false;
        EnemySpawnerConfigComponent spawnConfig = SystemAPI.GetSingleton<EnemySpawnerConfigComponent>();
        var random = new Random(123);
        var ecb = new EntityCommandBuffer(Allocator.Temp);

        for (int i = 0; i < spawnConfig.SpawnCount; i++)
        {
            Entity enemyEntity = ecb.Instantiate(spawnConfig.EnemyEntityPrefab);
            ecb.SetComponent(enemyEntity, new LocalTransform
            {
                Position = new float3
                {
                    x = random.NextFloat(0, spawnConfig.SpawnRadius),
                    y = random.NextFloat(0, spawnConfig.SpawnRadius),
                    z = 0,
                },
                Scale = 1,
                Rotation = quaternion.identity,
            });
        }

        ecb.Playback(state.EntityManager);
    }

I hope it helps!

rocky rapids
#

will just do it in update and disable the system

outer light
soft stag
#

they will work until spawn time matches first frame and is not needed to execute multiple times (new game/reload and etc)

rocky rapids
#

just to like spawn some prefab stuff and then erase the spawner entity

#

Actually as i think about it, i'd like to schedule a task and wait until it's finished to then spawn a player in the game world

#

For now gonna have the same mesh for each terrain chunk

#

So game goes like
Start
await Spawn meshes
Enable player and camera

light wyvern
rocky rapids
#

Well, how do i integrate them into systems

light wyvern
rocky rapids
#

Well. Im making a chunk system for a big world. For now i'd like to at least repeat the same mesh/material/collider, in a 96x96 grid while user is on loading screen scene

#

So when the world is set up(9216 chunks), i'd like to unload the loading screen scene and let player walk around

light wyvern
rocky rapids
#

Yeah, gonna use additive loading

#

Main menu -> Loading Screen(and Game scene in background preparing everything) -> Game

#

But well, loading screen is not a thing right now, so i'm trying to just setup the game scene

#

Have the prefab of a mesh, material and mesh collider

#

Need to place it 9216 times in a grid

#

And let player use Input.GetKey(...) to move around

light wyvern
rocky rapids
#

Yeah, i can

#

But the problem is with spawning prefabs and then not wasting runtime resources on useless systems

#

Schedule 9216 chunk spawns, wait for them to finish, and then let user spawn in

light wyvern
rocky rapids
#

After chunks are spawned, prefab is not needed anymore

#

As well as system which spawned those chunks

#

Another system might start which would dynamically change mesh and texture resolutions as player approaches some chunk or walks away

rocky rapids
#

Right now im spawning 9216 GameObjects with mesh, material, and collider

#

And it gives ~3 fps

#

So well, entities might give better performance

rocky rapids
#

Processing 9216 individual objects each frame seems to eat a lot of cpu resources

light wyvern
fickle vector
#

You can group your systems into ComponentSystemGroups and declare a condition for each group to update. For example SpawnGroup will only update if there is a GameLoadedTag, and CombatGroup will only update if there is a EntitySpawnedTag.

rocky rapids
#
for (int i = -3; i < 3; i++)
{
    for (int j = -3; j < 3; j++)
    {
        int x = i * 64;
        int z = j * 64;
        EntityCommandBuffer ecb = new(Allocator.Temp);
        Entity chunk = ecb.Instantiate(spawner.ValueRO.mesh);
        // ecb.AddComponent(chunk, new ChunkComponent());
        ecb.Playback(state.EntityManager);
        var transform = state.EntityManager.GetComponentData<LocalTransform>(chunk);
        transform.Position = new float3(x, 0, z);
        state.EntityManager.SetComponentData(chunk, transform);
    }
}```
iron ingot
rocky rapids
#

probably

iron ingot
#

or set SpawnCount to 0 when you finish spawning

rocky rapids
#

idk what is a enemyspawnerconfigcomponent

#

and what is spawncount

#

oh

#

it's not my code

iron ingot
#

oh, I guess I was looking at Sunny Valley Studio's example

rocky rapids
#

what's wrong with this sample above

iron ingot
#

using an ecb that you playback immediately is pointless, you might as well just use the EntityManager to instantiate immediately.

#

what you've written here is basically your own ecb... so if you use this code in a system that is playing back a buffer of requests, then this is perfect

#

the point of an ecb is to defer structural changes that interrupt jobs and invalidate lookups so that you can do them all at once later

rocky rapids
#

using ecb or not

iron ingot
#

just like you're doing it, but use the EntityManager

#

unless you're asking me something else?

#

the overall way you should try to organize your systems is to run as many systems as you can before making structural changes... so if you want to instantiate things in other systems, you might just write to a DynamicBuffer on your singleton entity with the data necessary for all the instantiations to happen at once later in the frame

#

you'll also notice that the built in system order has a lot of pre-built entity command buffers that you can use

#

but in your case, since you need to be able to edit the entity immediately upon instantiation, it might make sense for you to do it like you are right now and just position your system next to one of the existing entity command buffer systems in the frame

rocky rapids
#

i just opened up first YT guide and tried to go modify the output to suit my purposes

#

and it doesn't work

rocky rapids
#

i want to spawn them single time

#

just to test if unity can handle 9216 meshes on my pc

iron ingot
# rocky rapids and it doesn't work

the error you were getting was because you were trying to use the entity value passed from the entity command buffer with the EntityManager. The EntityCommandBuffer is for deferring commands to EntityManager. Use either one or the other, don't mix them.

rocky rapids
#

Alr so ig for spawning 9200 meshes at the same time i should use a buffer

#

Right?

#

Pass it somewhere and tell unity to execute all of the commands

iron ingot
#

I'm not sure where the misunderstanding is coming from... I think maybe what is unusual about ECS compared to what you might be used to is that it matters when things get executed in a frame. The point of the buffer is to control when in the frame the execution happens.

rocky rapids
#

i'm extremely new to ECS so yeah

iron ingot
#

if you are just testing something and don't care when in the frame it happens, then just use the entitymanager

rocky rapids
#

i only used buffers for compute shaders before

iron ingot
#

if you care when in the frame it happens, use the buffer

rocky rapids
#

alr then i shouldn't use buffer ig

rocky rapids
iron ingot
#

no, spawning is a structural change and structural changes have to happen on the main thread

#

thus why you would usually buffer them

#

(that and making structural changes while iterating through entities will break the lookups and so break the iteration loop)

rocky rapids
#

what is a structural change

rocky rapids
#

also is there a way to see entities in scene view

iron ingot
#

Entities aren't inherently visible. They're just data. If an entity represents something renderable, you should see that appear in the scene

rocky rapids
#

it appears in the game view

#

this green stuff

#

it's 9216 planes

iron ingot
#

you should see it in the scene view too

rocky rapids
#

i don't

iron ingot
#

you should 😛

rocky rapids
#

but i don't

#

i clearly see them in game

#

but don't see them in scene

iron ingot
#

I'm not familiar with anything that would cause them not to appear in the scene view

rocky rapids
#

might it be because i'm spawning a prefab

#

tho i love how fps went from 3 to 75

#

while i have 9216 entities on the scene

#

and not 9216 gameobjects

iron ingot
#

there's a number of things you could do to make this code cleaner, but none of this would have any effect on seeing something in game view that you don't in the scene view. The culprit is more likely to be in your scene viewport settings, shader settings, material settings, or something like that

rocky rapids
#

it's HDRP lit shader

#

and i touched nothing

#

just installed Entities and Entities Graphics

#

alr gtg to the job

#

cya

outer light
# soft stag they will work until spawn time matches first frame and is not needed to execute...

If you are used to OOP than indeed it looks awful. In Data Oriented design you have systems that runs constantly based on data. One way that works for me is to have an "IEnableableComponent" that I add to an entity and this triggers a spawn system and disable. I do this to add compoanion object to entities. Another way would be to have some Singleton data component that has some Bool flag. If the flag is True you could do the spawning once and set the bool flag to false. Either way its all doable. Just a bit different than OOP

soft stag