Search Unity

Send big data from Host to Clients

Discussion in 'Netcode for GameObjects' started by boyaregames, Jun 24, 2021.

  1. boyaregames

    boyaregames

    Joined:
    Jun 23, 2021
    Posts:
    76
    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)
     
  2. Saulotti

    Saulotti

    Joined:
    Oct 20, 2009
    Posts:
    19
    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.
     
    Last edited: Sep 17, 2021
  3. luke-unity

    luke-unity

    Joined:
    Sep 30, 2020
    Posts:
    306
    You can try using custom messages and a ReliableSequencedFragmented channel. That should allow you to send data up to ~65kb.
     
  4. cunibon

    cunibon

    Joined:
    May 6, 2020
    Posts:
    7
    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?
     
  5. Kyperr

    Kyperr

    Joined:
    Jul 15, 2016
    Posts:
    32
    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.
     
  6. Kyperr

    Kyperr

    Joined:
    Jul 15, 2016
    Posts:
    32
    I found an answer. Its the NetworkDelivery enum param that you can specify when you are sending a message.
     
  7. cunibon

    cunibon

    Joined:
    May 6, 2020
    Posts:
    7
    I wrote this today:


    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Unity.Netcode;
    5. using SimpleFileBrowser;
    6.  
    7. public class NetcodeFTP : NetworkBehaviour
    8. {
    9.     private int MagicNumber = 1300;
    10.  
    11.     private Dictionary<string, List<DataObject>> FileDatas = new Dictionary<string, List<DataObject>>();
    12.  
    13.     private struct DataObject
    14.     {
    15.         public int Index;
    16.         public byte[] Data;
    17.  
    18.         public DataObject(int Index, byte[] Data)
    19.         {
    20.             this.Index = Index;
    21.             this.Data = Data;
    22.         }
    23.     }
    24.  
    25.     public void Send(string path, string name)
    26.     {
    27.         StartCoroutine(SendEnumerator(path, name));
    28.     }
    29.  
    30.     public IEnumerator SendEnumerator(string path, string name)
    31.     {
    32.         byte[] Data = FileBrowserHelpers.ReadBytesFromFile(path); ;
    33.  
    34.         Debug.Log(path + " " + name);
    35.         Debug.Log(Data.Length);
    36.  
    37.         int PackageCount = Mathf.CeilToInt(Data.Length / MagicNumber);
    38.         Debug.Log(PackageCount);
    39.         for (int x = 0; x < PackageCount; x++)
    40.         {
    41.             if(x % 45 == 0)
    42.             {
    43.                 yield return new WaitForSeconds(0.5f);
    44.             }
    45.  
    46.             byte[] Packet;
    47.             if (Data.Length - (x * MagicNumber) < MagicNumber)
    48.             {
    49.                 Packet = new byte[Data.Length - (x * MagicNumber)];
    50.             }
    51.             else
    52.             {
    53.                 Packet = new byte[MagicNumber];
    54.             }
    55.  
    56.             for (int y = 0; y < Packet.Length; y++)
    57.             {
    58.                 Packet[y] = Data[x * MagicNumber + y];
    59.             }
    60.  
    61.             ReceiveServerRpc(name, Packet, x, Data.Length);
    62.         }
    63.  
    64.         yield return null;
    65.     }
    66.  
    67.  
    68.     [ServerRpc(RequireOwnership = false)]
    69.     public void ReceiveServerRpc(string name, byte[] Packet, int Current, int RealSize)
    70.     {
    71.         if(!FileBrowserHelpers.FileExists(Application.persistentDataPath + "/" + name))
    72.         {
    73.             if (!FileDatas.ContainsKey(name))
    74.             {
    75.                 FileDatas.Add(name, new List<DataObject>());
    76.                 Debug.Log("Added Key");
    77.  
    78.                 FileDatas[name].Add(new DataObject(Current, Packet));
    79.             }
    80.             else
    81.             {
    82.                 Debug.Log(Current);
    83.                 FileDatas[name].Add(new DataObject(Current, Packet));
    84.             }
    85.  
    86.             if (FileDatas[name].Count == Mathf.CeilToInt(RealSize / MagicNumber))
    87.             {
    88.                 FileDatas[name].Sort(SortByIndex);
    89.  
    90.                 byte[] File = new byte[RealSize];
    91.  
    92.                 foreach (DataObject Data in FileDatas[name])
    93.                 {
    94.                     Debug.Log(Data.Index);
    95.  
    96.                     for (int i = 0; i < Data.Data.Length; i++)
    97.                     {
    98.                         File[Data.Index * MagicNumber + i] = Data.Data[i];
    99.                     }
    100.                 }
    101.  
    102.                 FileBrowserHelpers.WriteBytesToFile(Application.persistentDataPath + "/" + name, File);
    103.  
    104.                 FileDatas.Remove(name);
    105.                 Debug.Log("Removed Key");
    106.             }
    107.         }
    108.     }
    109.  
    110.     static int SortByIndex(DataObject D1, DataObject D2)
    111.     {
    112.         return D1.Index.CompareTo(D2.Index);
    113.     }
    114. }
    115.  
    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.Dictionary`2[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.<CreateLoopSystem>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?
     
    Last edited: Jan 20, 2022
  8. Kyperr

    Kyperr

    Joined:
    Jul 15, 2016
    Posts:
    32
    I get that exact error on some similar code. I am sending it over custom messages though.
     
  9. Kyperr

    Kyperr

    Joined:
    Jul 15, 2016
    Posts:
    32
    https://forum.unity.com/threads/net...client-for-non-player-networkobjects.1217268/


    "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."
     
  10. cunibon

    cunibon

    Joined:
    May 6, 2020
    Posts:
    7
    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?
     

    Attached Files:

    • 340.png
      File size:
      55.5 KB
      Views:
      330