How Instantiate in systembase?

i need to pass data from mono to entity i created a buffer and filled it

class SpawnBot : UnityEngine.MonoBehaviour{
    public GameObject Prefab;
    public List<float3> ListBotPosition;
    class SpawnBotBaker : Baker<SpawnBot>{
        public override void Bake(SpawnBot authoring){
            var e = GetEntity(TransformUsageFlags.None);
            AddComponent(e, new SpawnBotComponent{ Prefab = GetEntity(authoring.Prefab, TransformUsageFlags.Dynamic) });
            AddComponent(e, new SpawnBotUpdateNeedTag{});
            var buffer = AddBuffer<BufferBotPosition>(e).Reinterpret<float3>();
            foreach(var pos in authoring.ListBotPosition){
                buffer.Add(pos);
                }
            }
        }
    }
public struct SpawnBotComponent : IComponentData{ public Entity Prefab; }
internal struct BufferBotPosition : IBufferElementData{ public float3 value; }
public readonly struct SpawnBotUpdateNeedTag : IComponentData, IEnableableComponent{}

next I need to extract these positions and create prefabs

public partial class SpawnBotSystem : SystemBase{
    protected override void OnUpdate(){
        var query = new EntityQueryBuilder(Allocator.Temp).WithAll<SpawnBotUpdateNeedTag>().WithAllRW<BufferBotPosition>().Build(EntityManager);
        NativeArray<ArchetypeChunk> chunks = query.ToArchetypeChunkArray(Allocator.Temp);
        for(int i = 0; i < chunks.Length; i++){ ReadBuffer(chunks[i]);}
        chunks.Dispose();
        }

    private void ReadBuffer(ArchetypeChunk chunk){
        BufferTypeHandle<BufferBotPosition> myElementHandle = GetBufferTypeHandle<BufferBotPosition>();
        BufferAccessor<BufferBotPosition> buffers = chunk.GetBufferAccessor(ref myElementHandle);
        for(int i = 0, chunkEntityCount = chunk.Count; i < chunkEntityCount; i++){
            DynamicBuffer<BufferBotPosition> buffer = buffers[i];
            for(int j = 0; j < buffer.Length; j++){
                Debug.Log(">>>" + buffer[j].value);

                // -> Instantiate To position "buffer[j].value"
                // it was in the ISystem
                // Entity newEntity = state.EntityManager.Instantiate(spawnBotComponent.ValueRO.Prefab);
                // state.EntityManager.SetComponentData(newEntity, LocalTransform.FromPosition(buffer[j].value));

                buffer.RemoveAt(j);
                }
            }
        }
    }

how to do it in systembase?
it’s just that in isystems, as I understand it, buffers cannot be used …

You can definitely used a command buffer by getting an EntityCommandBufferSystem singleton from SystemAPI.

1 Like

can you provide a link to an example?
I can’t find an example for my case…

Add: now my script is like this

[BurstCompile]
public partial struct SpawnerSystem : ISystem{
    public void OnCreate(ref SystemState state){}
    public void OnDestroy(ref SystemState state){}
    [BurstCompile]
    public void OnUpdate(ref SystemState state){
        foreach(RefRW<SpawnBotComponent> spawnBotComponent in SystemAPI.Query<RefRW<SpawnBotComponent>>()){
            CheckNeedSpawner(ref state, spawnBotComponent);
            }
        }

    private void CheckNeedSpawner(ref SystemState state, RefRW<SpawnBotComponent> spawnBotComponent){
        if(spawnBotComponent.ValueRO.SpawnNeed){
            for(int x = -2; x < 2; ++x){
                for(int z = -2; z < 2; ++z){
                    Entity newEntity = state.EntityManager.Instantiate(spawnBotComponent.ValueRO.Prefab);
                    state.EntityManager.SetComponentData(newEntity, LocalTransform.FromPosition(new float3(x, 0f, z)));
                    }
                }
            spawnBotComponent.ValueRW.SpawnNeed = false;
            }
        }
    }

Something like this:

public void OnUpdate(ref SystemState state) {
    EndSimulationEntityCommandBufferSystem.Singleton commandBufferSystem = SystemAPI.GetSingleton<EndSimulationEntityCommandBufferSystem.Singleton>();
    EntityCommandBuffer commandBuffer = commandBufferSystem.CreateCommandBuffer(state.WorldUnmanaged);
    // Use commandBuffer here. Pass it to your methods.

    // I use it like this
    SomeJob job = new() {
        ...
        commandBuffer = commandBuffer.AsParallelWriter()
    };
    state.Dependency = job.ScheduleParallel(this.query, state.Dependency);
}
1 Like

I’m sorry but I don’t understand, I’m just new to entities… I need to transfer values from an already created buffer and not create a new buffer, or how it works, I don’t understand yet …

and the old function seems to be how to pass singlets inside

    public void OnUpdate(ref SystemState state){
        var ecbSingleton = SystemAPI.GetSingleton<EndSimulationEntityCommandBufferSystem.Singleton>();
        var job = new SpawnBotUpdateJob{
            ecb = ecbSingleton.CreateCommandBuffer(state.WorldUnmanaged).AsParallelWriter()
            };
        state.Dependency = job.ScheduleParallelByRef(state.Dependency);
        }
[WithAll(typeof(SpawnBotUpdateNeedTag))]
    private partial struct SpawnBotUpdateJob : IJobEntity{
        public EntityCommandBuffer.ParallelWriter ecb;
        public void Execute([ChunkIndexInQuery] int chunkIndex, in Entity entity, in TargetLocation target, in LocalTransform transform){
............. maybe here call buffer?
            }

        }

maybe there already call a buffer somehow, I still don’t understand how it works …

I suggest you take another aproach to the problem. Instead of spawning gameobjects at first then transfering data from them to the newly spawned entities, the process should be like this:

  1. Prepare a prefab entity (either by IBaker at baketime, or by EntityManager.CreateEntity at runtime)
  2. Spawn some entities using that prefab entity, and set their components’ data
  3. Collect data** from your entities, put them in some buffers
  4. Spawn your gameobjects and apply these data to them

The idea is using GameObject only as a view - a place for you to dump the data from the ECS world. For me, this approach is much more intuitive. The ECS world would govern all data and logic, where as the GO world would only act as a view, a presenter for your data.

** You should only collect just enough data for the GOs, for they are just views, they won’t need everything.

Indeed this approach couldn’t solve more complicated problems like when the data would go back and forth between the 2 worlds. I haven’t reached that phase of my project yet, unfortunately.

1 Like

my situation is as follows - the location data of objects is stored on the server, a mono object with a socket script makes a request to the server, receives data about where and what object is located, then this information needs to be transferred to entities and managed there already, and also after a certain time transmit data again in mono, mono in turn sends data again to the server…
(the transfer script and the server itself are already working, only with entities need to combine this …)

This changes nothing to my suggestion. You can think of the mono object that receives the server’s responses as another input interface. You’d likely have a place to receive user’s input and transfer that data to the ECS world too.

You can study this example from Unity about how to handle user’s input and make changes to the ECS world:
https://github.com/Unity-Technologies/EntityComponentSystemSamples/blob/bc1ffa52d52e5781c4ec8b153f0c8beea430d2e8/PhysicsSamples/Assets/Common/Scripts/DemoInputGatheringSystem.cs#L6

I think you can read a couple of articles about this concept “OOP Abstraction Layer” to get the idea of how to handle external signals but also keep the 2 worlds separated as much as possible:
https://www.sebaslab.com/oop-abstraction-layer-in-a-ecs-centric-application/
https://www.sebaslab.com/ecs-abstraction-layers-and-modules-encapsulation/

(The author doesn’t use Unity ECS but his own ECS solution, so you might get some hiccups reading his code. Just focus on the idea discussed in those articles.)

1 Like

Thanks for the tips, I will read

Might I know how your server is coded? I think it’s best to have your server coded in ECS too according all the information I’ve got from you up until now.

no, there is a regular dedicated server on Linux, the transmitter itself is written in PHP (ratchet), in fact it works as a transmitter in a chat, that is, it receives a string and sends it to other clients with the same session, well, plus a script that separately processes insert and read data from mysql database…
Unfortunately, in the server part, I’m still only in php …