(1.0.8) Composite causing Ghost Data to not always sync

Loading up my existing project for some reason my component is not always syncing.
The pair on the left are syncing fine, the pair on the right are not - they both exist at the same time on the client but only 1 is working.
The data is just a giant chunk of 512 bytes.

    [GhostComponent]
    internal struct Packet : IComponentData
    {
        [GhostField(Composite = true)]
        public FixedBytes512 Buffer;
    }

    [Serializable]
    public struct FixedBytes512 : IEquatable<FixedBytes512>
    {
        public FixedBytes64 Offset0000;
        public FixedBytes64 Offset0064;
        public FixedBytes64 Offset0128;
        public FixedBytes64 Offset0192;
        public FixedBytes64 Offset0256;
        public FixedBytes64 Offset0320;
        public FixedBytes64 Offset0384;
        public FixedBytes64 Offset0448;

        public unsafe bool Equals(FixedBytes512 other)
        {
            fixed (void* ptr = &this)
            {
                return UnsafeUtility.MemCmp(ptr, &other, sizeof(FixedBytes512)) == 0;
            }
        }

        public override int GetHashCode()
        {
            return (int)math.hash(math.hashwide(new int4x2(
                new int4(this.Offset0000.GetHashCode(), this.Offset0064.GetHashCode(), this.Offset0128.GetHashCode(), this.Offset0192.GetHashCode()),
                new int4(this.Offset0256.GetHashCode(), this.Offset0320.GetHashCode(), this.Offset0384.GetHashCode(), this.Offset0448.GetHashCode()))));
        }
    }

    [Serializable]
    public struct FixedBytes64 : IEquatable<FixedBytes64>
    {
        public long Offset00;
        public long Offset08;
        public long Offset16;
        public long Offset24;
        public long Offset32;
        public long Offset40;
        public long Offset48;
        public long Offset56;

        public unsafe bool Equals(FixedBytes64 other)
        {
            fixed (void* ptr = &this)
            {
                return UnsafeUtility.MemCmp(ptr, &other, sizeof(FixedBytes64)) == 0;
            }
        }

        public override int GetHashCode()
        {
            return (int)math.hash(math.hashwide(UnsafeUtility.As<FixedBytes64, int4x4>(ref this)));
        }
    }

If I make Composite=false it work fine.

Hey Turtle,
Thanks for the report. The team did some work recently with regards to Composite, I’ll see if I can see why this is happening. Looks like our test coverage needs to be expanded too.
Can you file it as a Unity bug, for tracking purposes? Cheers.

IN-40905

1 Like

Yep, the CalculateChangeMask code-generation for Packet is just completely wrong here. In the generated file Temp/NetcodeGenerated/[YourFolderStructure]/PacketSerializer.cs, method CalculateChangeMask roughly on line 826. We clobber the changemask every 64 bytes.

Note: You may need to modify your .globalConfig in your project root to enable:

unity.netcode.sourcegenerator.write_files_to_disk=1```

We'll get this fixed, but yeah please use your workaround for now.
1 Like