There is a ghost with data in the buffer. Blob reference can’t be GhostFIeld, ok, disable sending. And everything should be fine. But apparently because of the specifics of serialization of buffer changes something goes wrong and on the client (only on the client) buffer differs from the version on the server, it is the data that differs. In the example there are 3 fields - ghost id, non-ghost id and id stored in blob. Everything is fine on the server, but on the client, in the end there is an element with a correct ghost id, but all other fields have completely incorrect values.
If I understand correctly, then due to serialization of ghosts unity on the client can use on quite the same data in the local buffer when receiving changes from the server.
The doc says that [GhostField(SendData=false)] is allowed to use buffers, with the note that I have to set the value initially - initially it is set, but I have to manually control these values in case of changes on the server?
Am I missing something? Some option or the only way out is to store such data in a separate repository
using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.NetCode;
using UnityEngine;
using Random = Unity.Mathematics.Random;
namespace DotsInventory
{
[GhostComponent()]
public partial struct TestBufferElement : IBufferElementData
{
public struct TestBlob
{
public int id;
}
[GhostField] public int id;
[GhostField(SendData = false)] public int sameId;
[GhostField(SendData = false)] public BlobAssetReference<TestBlob> blob;
}
public class TestAuthoring : MonoBehaviour
{
private class TestBaker : Baker<TestAuthoring>
{
public override void Bake(TestAuthoring authoring)
{
var e = GetEntity(TransformUsageFlags.None);
var els = AddBuffer<TestBufferElement>(e);
for (int i = 0; i < 100; i++)
{
var blob = new BlobBuilder(Allocator.Temp);
ref var root = ref blob.ConstructRoot<TestBufferElement.TestBlob>();
root.id = i;
var asset = blob.CreateBlobAssetReference<TestBufferElement.TestBlob>(Allocator.Persistent);
blob.Dispose();
AddBlobAsset(ref asset, out _);
els.Add(new TestBufferElement() { id = i, sameId = i, blob = asset });
}
}
}
}
[BurstCompile]
[WorldSystemFilter(WorldSystemFilterFlags.ServerSimulation)]
[UpdateInGroup(typeof(SimulationSystemGroup))]
partial struct TestSystem : ISystem
{
private Random _rnd;
[BurstCompile]
public void OnCreate(ref SystemState state)
{
_rnd = Random.CreateFromIndex(234234234);
}
[BurstCompile]
public void OnDestroy(ref SystemState state)
{
}
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
foreach (var els in SystemAPI.Query<DynamicBuffer<TestBufferElement>>())
{
if (els.Length != 1)
els.RemoveAt(_rnd.NextInt(0, els.Length));
}
}
}
}