#Need a way to store data in an array over a NetworkList

1 messages · Page 1 of 1 (latest)

obtuse falcon
#

I've been writing a script recently for chests in my multiplayer game, and I need a way to store a list of its items that is synced between the clients. I tried using a NetworkVariable array but that didn't work for some reason. Unity says that it has a NetworkList type which seems like it should be able to accomplish my goal, but I need advice on how to structure the data I need to be sending. My current class for items looks like this

public struct ItemNetworkStruct : INetworkSerializable
{
    public Item.ItemType type;
    public int amount;
    //Attribute values
    public ItemAttribute.AttributeName[] attributeNames;
    public float[] attributeValues;
    public FixedString512Bytes attributeInfo;
    //Spell values
    public Spell.SpellType spellType;
    public SpellAttribute.AttributeType[] spellAttributeTypes;
    
    public float[] spellAttributeValues;
    public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
    {
        serializer.SerializeValue(ref type);
        serializer.SerializeValue(ref amount);
        serializer.SerializeValue(ref attributeNames);
        serializer.SerializeValue(ref attributeValues);
        serializer.SerializeValue(ref spellType);
        serializer.SerializeValue(ref spellAttributeTypes);
        serializer.SerializeValue(ref spellAttributeValues);
        serializer.SerializeValue(ref attributeInfo);
    }
}```
This has been working so far for what I need, but the attribute and float arrays are reference types, so I can't use this struct in a NetworkList. I need some advice on how to structure this so I can store the data in an array-esque format without using reference types, if possible, so I can use it in a network list.
plucky cave
#

You could use a Span<T> instead of T[].

obtuse falcon
#

Thank you, that looks like exactly what I need.

plucky cave
#

you're welcome 😄

obtuse falcon
#

Since I've never worked with it before, do you have advice on how to implement them?
Unity told me first that I needed to mark it as a ref, giving me
public ref Span<float> spellAttributeValues;
instead of the original
public float[] spellAttributeValues;
However when I do this its throwing an error for spellAttributeValues telling me
CS0501: ItemNetworkStruct.spellAttributeValues() must declare a body because it is not marked abstract, extern, or partial.
I'm looking at the C# documentation for Span<T> right now and it looks like they just declare them (the example they give is Span<byte> nativeSpan, which throws an error in Unity.
I've also tried marking the entire ItemNetworkStruct as a ref which fixes the issue, but throws a new one because ref structs can't implement interfaces, so I wouldn't be able to use it over the network.

plucky cave
#

Huh. To be honest, I've never really used them myself.

obtuse falcon
#

😛

plucky cave
#

But with the methods that the BufferSerializer provides, I think you can "manually" serialize those arrays of yours; You could even write extension methods for it (which I would recommend).

#

It's honestly really weird how they implemented it though. And especially that they don't let you serialize byte arrays or streams.

obtuse falcon
#

Does serializer.SerializeValue(ref spellAttributeValues); not do that?
I'm fairly new to the more system-oriented stuff, despite working with games for a while.
The most extension methods I've written are just ones to convert my item structs to classes, and vice versa.

plucky cave
#

attributeValues is a reference type, so you won't be able to use it in SerializeValue.
Extension methods are static methods inside static classes, whose first parameters have the this keyword, respectively.
They can be called like instance methods, but behave like the static methods they are.

Apparently, Unity actually saw people using them to serialize more complex values:
https://docs-multiplayer.unity3d.com/netcode/current/advanced-topics/custom-serialization/
Since that's a possibility, you might want to consider not making a struct for those values in the first place, since structs are not supposed to be larger than 16 bytes: https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/choosing-between-class-and-struct

obtuse falcon
#

yeah, for the most part Items are stored in classes. The only two extension methods I wrote were Item.ToStruct() and ItemNetworkStruct.ToClass(). I only convert the Item class into a struct to send it over the network, then immediatly reconstruct it as a class when I receive it, do you think that's bad practice?

#

I'll take a look at the custom serialization docs.

obtuse falcon
#

So most of this went over my head, and even just using the functions on that article unity is being mean 🙂 , so I think I'm going to try and use NativeArrays, as it looks like unity has a implementation guide on that.
Thank you for all your help!