如何在统一的多人游戏中得到一个2 d的字符串数组穿越光子网络的方法

问题描述 投票:0回答:1

我正试图序列化一个二维字符串数组并通过网络发送。

我有几个想法,但我似乎被api或效率挡住了......我真的不想把一个小的二维数组序列化并通过网络发送10次。

我有一个玩家购物车里的物品列表,我想让玩家可以从购物车里偷东西,这样其他玩家就可以看到购物车里的东西了,如果我使用onphotonserializeview,我想我可以用delimeter和stream.sendnext将二维字符串数组转换为一维字符串数组。

如果我使用onphotonserializeview,我想我可以把二维的字符串数组转化为一维的字符串数组,再加上delimeter和stream.sendnext的delimeted行,然后在另一边重组......这种功能的一些变化。

public void serialize_merchandise_list() {


    int width = 0;
    int length = 0;

    while((width < cart_list_width) && (length < cart_list_width)) {          

        width++;

        if (width >= cart_list_width) {
            length++;
            width = 0;
        }

        // convert to bytes and then to string and append
           System.Text.ASCIIEncoding.ASCII.GetBytes(merchandise_items[width, length]));

    }
}

但这样做是不必要的,是操作时间上的噩梦......我想按需操作......。

我打算做一个punrpc,但我无法得到一个返回值或参考参数。

建议?

我想

与推车相撞 --> 是 --> 显示列表

你想从车上偷东西吗 --> 是 --> 显示列表

否则--> 走你的婚姻之路。

c# unity3d game-development photon
1个回答
0
投票

一个一维的字符串数组将是......。对光子来说没有问题.

所以我想你可以将数组扁平化,并额外发送第二个大小--让我们将它命名为元素大小(与第一个相反--元素数)作为参数。

例如,让我们说你的数组看起来像

string[,] array2D = new string[4,2]{{"a", "b"}, {"c","d"}, {"e","f"}, {"g","h"}};

那么你就会知道第二个(元素大小)维度,使用硬编码或 GetLength(int)

var elementSize = array2D.GetLength(1);

然后您可以使用

string[] arrayFlat = array2D.Cast<string>().ToArray();

所以,你会通过光子发送这两个信息(我对光子的细节不了解),但fafaik你可以做到这一点,而不必持续发送。这两个参数将是

int elementSize, string[] arrayFlat

在这种情况下,其数值为

2, string[8]{"a","b","c","d","e","f","g","h"}

所以在一起。

public void SendArray2D()
{
    int elementSize = array2D.GetLength(1);
    string[] arrayFlat = array2D.Cast<string>().ToArray();

    photonView.RPC(nameof(ReceiveArray2D), RpcTarget.All, elementSize, (object) arrayFlat);
}

然后在接收器部分你会得到

int elementSize = 2, string[] arrayFlat = string[8]{"a","b","c","d","e","f","g","h"}

并要把它转换回来。你已经知道第二维度 elementSize = 2 所以,为了得到第一个,你只需做到

var elementCount = arrayFlat.Length / elementSize; // = 4

所以你知道你要填充的2D数组将是

string[,] array2D = new string[elementCount, elementSize]; // = 4,2

然后你就可以简单地迭代它,做一些类似于

for (var x = 0; x < elementCount; x++)
{
    for (int y = 0; y < elementSize; y++)
    {
        array2D[x, y] = arrayFlat[x * elementSize + y];
    }
}

所以在一起

[PunRpc]
public void ReceiveArray2D(int elementSize, string[] arrayFlat)
{
    var elementCount = arrayFlat.Length / elementSize;
    array2D = new string[elementCount, elementSize];
    for (var x = 0; x < elementCount; x++)
    {
        for (int y = 0; y < elementSize; y++)
        {
            array2D[x, y] = arrayFlat[x * elementSize + y];
        }
    }

    // Could also e.g. call some event like
    OnReceivedArray2D?.Invoke (array2D);
}

public event Action<string[,]> OnReceivedArray2D;

所以你可以通过以下方式将监听器附加到事件上

reference.OnReceivedArray2D += SomeHandler;

private void SomeHandler(string [,])
{
    // ...
}

或者你也可以实现一个类,将你的数据存储在一个平面数组中,但让你像访问一个二维数组一样访问它(一般来说,二维数组是作为一个平面数组存储在内存中的)。

[Serializable]
public class SerializableArray2D
{
    public readonly string[] ArrayFlat;
    public readonly ElementSize;

    public SerializableArray2D(int elementSize, string[] arrayFlat)
    {
        ElementSize = elementSize;
        ArrayFlat = arrayFlat;
    }

    public SerializableArray2D(string[,] array2D) : this(array2D.GetLength(1), array2D.Cast<string>().ToArray()) { }

    public SerializableArray2D(int elementSize, int elementCount) : this(elementSize, new string[elementCount]){}

    public string this[int x, int y]
    {
        get { return ArrayFlat[x * ElementSize + y]; }
        set { ArrayFlat[x * ElementSize + y] = value; }
    }
}

用法是例如:Initialize it。

var array2D = new string[4,2]{{"a", "b"}, {"c","d"}, {"e","f"}, {"g","h"}};
var serializableArray2D = new SerializableArray2D(array2D);

用于访问特定的指数,比如在一个2D数组中。

string example = serializableArray2D[1,1];
serializableArray2D[3,0] = "example";

为了发送它

photonView.RPC(nameof(Receive), RpcTarget.All, serializableArray2D.ElementSize, (object)serializableArray2D.ArrayFlat);

而当收到它时

[PunRPC]
public void Receive(int elementSize, string[] arrayFlat)
{
    serializableArray2D = new SerializableArray2D(elementSize, arrayFlat);

    // Again e.g. call an event
    OnReceivedSerializableArray2D?.Invoke(serializableArray2D);
}

public event Action<SerializableArray2D> OnReceivedSerializableArray2D;
© www.soinside.com 2019 - 2024. All rights reserved.