如何在 Unity 多人游戏中通过光子网络获取 2D 字符串数组



我正在尝试序列化一个 2D 字符串数组以通过网络发送。

我有几个想法,但我似乎被 api 或效率阻止了。我真的不想序列化并通过网络每秒发送 10 次小型 2D 数组,而我只需要它,当我与某物碰撞并询问信息时。

我有一个玩家购物车中的物品列表。我想让从购物车中偷东西没问题,这样其他玩家必须能够看到购物车里的东西。

如果我使用 onphotonserializeview,我认为我可以将扁平化的 2d 字符串数组转换为带有分隔符的 1D 字符串数组,然后 stream.sendnext 分隔线并在另一侧重新构造,或者该功能的某种变体。

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 但我无法获得返回值或 ref 参数。这里最好的方法是什么?

我想要:

  1. 与购物车相撞

  2. 你想从购物车偷东西吗 --> 是的 --> 显示列表

  3. 否则 -->继续你的路

Afaik 一维字符串数组对 Photon 来说不是问题。

所以我想你可以把数组展平,另外发送第二个大小 - 让我们将其命名为元素大小(与第一个相反 - 元素计数(作为参数。

例如,假设您的数组看起来像

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

然后,您将使用硬编码或GetLength(int)来了解第二个(elementSize(维度

var elementSize = array2D.GetLength(1);

您只需

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

所以你会通过光子发送这两个信息(我不知道光子的细节(,但你可以这样做一次,而不必连续发送。这两个参数将是

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 [,])
{
// ...
}

或者,您可以实现一个类,该类将数据存储在平面数组中,但允许您像 2D 数组一样访问它(通常,2D 数组无论如何都作为平面数组存储在内存中(

[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; }
}
}

用法是例如初始化它

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;

相关内容

  • 没有找到相关文章

最新更新