@Antypodish So, i tried to play around with the solution i got, and once i begin moving around, diagonal moves give big spikes : from 7-14ms, up to 74ms. The slowest being the creation system. It takes around 50 ms to execute when i’m callin upon the generation system. And currently it’s only a simple one that returns a value from system.random
This is still an improvement from the 8 seconds for the previous version (yes, unplayable, i know). So i want to jobify the creation part. The problem i’m facing is how to jobify that part. No matter what i try, i’m getting the erro saying i’m writing on entities i shouldn’t.
Here is the code :
Normal Method
private void CreateBlocks(ChunkData data)
{
float3 chunkOrigin = new float3(data.CurrentPosition.x - (data.Size.x / 2.0f), data.CurrentPosition.y - (data.Size.y / 2.0f), data.CurrentPosition.z + 1);
//Get reference to the chunk so we can iterate only on the concerned blocks
var refs = BootStrap.GameData.Players.First(p => p.Id == data.PlayerId);
//Get the array with the blocks
refs.Blocks = new NativeArray<Entity>(data.Length, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
//Instantiate the entities
EntityManager.CreateEntity(BootStrap.BlockArchetype, refs.Blocks);
var scale = new Scale { Value = BootStrap.Settings.Map.BlockSize };
//Iterate over all positions and generate the blocks
for (int y = 0, idx = 0; y < data.Size.y; y++)
{
for (int x = 0; x < data.Size.x; x++, idx++)
{
//Get entity
var block = refs.Blocks[idx];
//Set block view owner
var id = new BlockIdentityData { Id = data.PlayerId };
//Set position
var bPosition = new Position { Value = new float3(chunkOrigin.x + x, chunkOrigin.y + y, chunkOrigin.z) };
//Generate block type
var bData = new BlockData { Code = GenerateCode(bPosition.Value, 0, 0, ResourceManager.Textures.Length) };
//Apply changes
Buffer.SetComponent(block, bData);
Buffer.SetComponent(block, scale);
Buffer.SetComponent(block, bPosition);
Buffer.SetComponent(block, data);
Buffer.SetComponent(block, id);
//Add marker so we can update mesh instance renderer
Buffer.AddComponent(block, new BlockViewUpdate());
}
}
}
Jobified method (after many tries and corrections)
private void CreateBlocksAsync(ChunkData data)
{
float3 chunkOrigin = new float3(data.CurrentPosition.x - (data.Size.x / 2.0f), data.CurrentPosition.y - (data.Size.y / 2.0f), data.CurrentPosition.z + 1);
//Get reference to the chunk so we can iterate only on the concerned blocks
var refs = BootStrap.GameData.Players.First(p => p.Id == data.PlayerId);
//Get the array with the blocks
refs.Blocks = new NativeArray<Entity>(data.Length, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
//Instantiate the entities
EntityManager.CreateEntity(BootStrap.BlockArchetype, refs.Blocks);
var scale = new Scale { Value = BootStrap.Settings.Map.BlockSize };
new CreateBlockJob
{
Blocks = refs.Blocks,
Buffer = Buffer,
Id = data.PlayerId,
Origin = chunkOrigin,
Scale = scale,
Width = data.Size.x
}.Schedule(refs.Blocks.Length, 1).Complete();
}
The job
//Of course can't burst compile an ECB
//[BurstCompile]
public struct CreateBlockJob : IJobParallelFor
{
public NativeArray<Entity> Blocks;
[ReadOnly] public EntityCommandBuffer Buffer;
public int Id;
public float3 Origin;
public Scale Scale;
public int Width;
public void Execute(int index)
{
var block = Blocks[index];
var id = new BlockIdentityData { Id = Id };
var y = index / Width;
var x = index - y * Width;
var bPosition = new Position { Value = new float3(Origin.x + x, Origin.y + y, Origin.z) };
var bData = new BlockData { Code = BootStrap.GenerationRule.GetValue((int)bPosition.Value.x, (int)bPosition.Value.y, (int)bPosition.Value.z) };
Buffer.SetComponent(block, bData);
Buffer.SetComponent(block, Scale);
Buffer.SetComponent(block, bPosition);
Buffer.SetComponent(block, bData);
Buffer.SetComponent(block, id);
//Add marker so we can update mesh instance renderer
Buffer.AddComponent(block, new BlockViewUpdate());
}
}
I also have to do a similar thing to the creation with movement. I’m trying to reuse existing blocks rather than destroying the ones outside the view and creating new ones.
I also thought about simply marking for generation the created blocks, and doing the generation in another system, but i would also need to change data, and mark them for update by adding a component.