Hello!
I am making a local multiplayer and i need to send from host to the clients an Image(JPG).
All needed data of the game exist only on a Host side (just strings, images)
I cannot do that via Rpc cuz of packet limitation. So how to do that?
(Sorry for bad english)
I’m also looking for an answer on this. Using MLAPI.
Edit:
What I did so far: I’ve created a Coroutine in my server to send a small chunk of the data each update cycle, considering the limit of 1500 bytes per RPC call. I’m sending roughly 1200 per RPC per call.
Considering that I just do this once the player have just connected, while loading the level, and the information is not crucial for the gameplay, I don’t think it will be a problem for the player to see the content loading through 1 or 2 seconds.
You can try using custom messages and a ReliableSequencedFragmented channel. That should allow you to send data up to ~65kb.
Is the Maximum amount of Data really 1500 bytes? And is there a Limit to how many Rpc calls i can make in a given time?
What would it look like to use a custom channel like that with NGO? Do you have a link to the documentation? I’m just looking for a point of entry.
I found an answer. Its the NetworkDelivery enum param that you can specify when you are sending a message.
I wrote this today:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Netcode;
using SimpleFileBrowser;
public class NetcodeFTP : NetworkBehaviour
{
private int MagicNumber = 1300;
private Dictionary<string, List<DataObject>> FileDatas = new Dictionary<string, List<DataObject>>();
private struct DataObject
{
public int Index;
public byte[] Data;
public DataObject(int Index, byte[] Data)
{
this.Index = Index;
this.Data = Data;
}
}
public void Send(string path, string name)
{
StartCoroutine(SendEnumerator(path, name));
}
public IEnumerator SendEnumerator(string path, string name)
{
byte[] Data = FileBrowserHelpers.ReadBytesFromFile(path); ;
Debug.Log(path + " " + name);
Debug.Log(Data.Length);
int PackageCount = Mathf.CeilToInt(Data.Length / MagicNumber);
Debug.Log(PackageCount);
for (int x = 0; x < PackageCount; x++)
{
if(x % 45 == 0)
{
yield return new WaitForSeconds(0.5f);
}
byte[] Packet;
if (Data.Length - (x * MagicNumber) < MagicNumber)
{
Packet = new byte[Data.Length - (x * MagicNumber)];
}
else
{
Packet = new byte[MagicNumber];
}
for (int y = 0; y < Packet.Length; y++)
{
Packet[y] = Data[x * MagicNumber + y];
}
ReceiveServerRpc(name, Packet, x, Data.Length);
}
yield return null;
}
[ServerRpc(RequireOwnership = false)]
public void ReceiveServerRpc(string name, byte[] Packet, int Current, int RealSize)
{
if(!FileBrowserHelpers.FileExists(Application.persistentDataPath + "/" + name))
{
if (!FileDatas.ContainsKey(name))
{
FileDatas.Add(name, new List<DataObject>());
Debug.Log("Added Key");
FileDatas[name].Add(new DataObject(Current, Packet));
}
else
{
Debug.Log(Current);
FileDatas[name].Add(new DataObject(Current, Packet));
}
if (FileDatas[name].Count == Mathf.CeilToInt(RealSize / MagicNumber))
{
FileDatas[name].Sort(SortByIndex);
byte[] File = new byte[RealSize];
foreach (DataObject Data in FileDatas[name])
{
Debug.Log(Data.Index);
for (int i = 0; i < Data.Data.Length; i++)
{
File[Data.Index * MagicNumber + i] = Data.Data[i];
}
}
FileBrowserHelpers.WriteBytesToFile(Application.persistentDataPath + "/" + name, File);
FileDatas.Remove(name);
Debug.Log("Removed Key");
}
}
}
static int SortByIndex(DataObject D1, DataObject D2)
{
return D1.Index.CompareTo(D2.Index);
}
}
I use the IEnumerator to stop it from hitting the limit of 65527.
but now i get this error
KeyNotFoundException: The given key ‘187’ was not present in the dictionary.
System.Collections.Generic.Dictionary2[TKey,TValue].get_Item (TKey key) (at <47ab72e0328040438980f9c23608e1ec>:0) Unity.Netcode.NetworkManager.TransportIdToClientId (System.UInt64 transportId) (at Library/PackageCache/com.unity.netcode.gameobjects@1.0.0-pre.4/Runtime/Core/NetworkManager.cs:1285) Unity.Netcode.NetworkManager.HandleRawTransportPoll (Unity.Netcode.NetworkEvent networkEvent, System.UInt64 clientId, System.ArraySegment
1[T] payload, System.Single receiveTime) (at Library/PackageCache/com.unity.netcode.gameobjects@1.0.0-pre.4/Runtime/Core/NetworkManager.cs:1345)
Unity.Netcode.NetworkManager.OnNetworkEarlyUpdate () (at Library/PackageCache/com.unity.netcode.gameobjects@1.0.0-pre.4/Runtime/Core/NetworkManager.cs:1177)
Unity.Netcode.NetworkManager.NetworkUpdate (Unity.Netcode.NetworkUpdateStage updateStage) (at Library/PackageCache/com.unity.netcode.gameobjects@1.0.0-pre.4/Runtime/Core/NetworkManager.cs:1152)
Unity.Netcode.NetworkUpdateLoop.RunNetworkUpdateStage (Unity.Netcode.NetworkUpdateStage updateStage) (at Library/PackageCache/com.unity.netcode.gameobjects@1.0.0-pre.4/Runtime/Core/NetworkUpdateLoop.cs:149)
Unity.Netcode.NetworkUpdateLoop+NetworkEarlyUpdate+<>c.b__0_0 () (at Library/PackageCache/com.unity.netcode.gameobjects@1.0.0-pre.4/Runtime/Core/NetworkUpdateLoop.cs:172)
none of the Debug.Logs i put in the ServerRpc trigger when i get this error
Any Idea?
I get that exact error on some similar code. I am sending it over custom messages though.
https://discussions.unity.com/t/866500
“A workaround is to increase the Message Buffer Size (max 65535) in the UNet Transport component. This increases the number of objects that can exist on the server prior to client connection. Note that there will still be a limit, just a higher one.”
This helped with sending all the Messages but I´m still having problems. Some images still come out corrupted in the last few pixels and then can’t be turned into a Texture2D. Would you mind sharing your solution?