我正在尝试序列化一个 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 参数。这里最好的方法是什么?
我想要:
与购物车相撞
你想从购物车偷东西吗 --> 是的 --> 显示列表
否则 -->继续你的路
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;