Search Unity

How to send a photo or a long text? with an array?

Discussion in 'Unity Transport' started by Farshadfarzan368, Jan 18, 2023.

  1. Farshadfarzan368

    Farshadfarzan368

    Joined:
    Sep 10, 2022
    Posts:
    73
    How to send a photo or a long text? with an array? In unity transport
     
  2. simon-lemay-unity

    simon-lemay-unity

    Unity Technologies

    Joined:
    Jul 19, 2021
    Posts:
    441
    You would use a pipeline with fragmentation enabled to get the data over the network. How you serialize the data is up to you, but for things like pictures I'd just go with the raw data directly (in whatever format your picture is in).
    DataStreamWriter
    has a
    WriteBytes
    method that takes a raw pointer and a length for these kinds of scenarios.

    Note however that Unity Transport is not designed to send large blobs of data like this. It is designed for small and frequent messages, which is a more common pattern in multiplayer games. I'd recommend looking into ways to avoid having to send such large payloads. For example, if the pictures are from a known set, it's simpler to have clients include the entire set and having the server only send the ID of the picture. Otherwise you might also want to look into using a separate service to store the data. For example you might have a player identity service which could store player avatars. Server would then only send the player IDs to the clients, which would download the avatars separately from the identity service using HTTP requests.
     
  3. Farshadfarzan368

    Farshadfarzan368

    Joined:
    Sep 10, 2022
    Posts:
    73
    Thank you for your reply
     
  4. simon-lemay-unity

    simon-lemay-unity

    Unity Technologies

    Joined:
    Jul 19, 2021
    Posts:
    441
    In what way does it fail? Just stating that it doesn't work isn't very helpful.

    Have you verified that your picture fits within the payload? Your client code is only set up to send messages not larger than 2000 bytes. Not many images will fit into that. Furthermore, you should check the different errors returned by the transport methods. Both
    BeginSend
    and
    EndSend
    can return error codes, and all
    DataStreamWriter.Write*
    methods return the status of the write.
     
  5. Farshadfarzan368

    Farshadfarzan368

    Joined:
    Sep 10, 2022
    Posts:
    73
    ============
    new test:
    size eee.jpg is 823kb
    start test :
    public void SendPhoto()
    {
    // new test load in file
    byte[] data2 = File.ReadAllBytes("D:\\eee.jpg");
    // save file is ok
    File.WriteAllBytes("D:\\eee2x.jpg", data2);
    NativeArray<byte> nb = new NativeArray<byte>(data2, Allocator.Temp);
    print("m_clientDrive.BeginSend=> " + m_clientDrive.BeginSend(_fragmentedPipeline, m_clientToServerConnection, out var senddata));
    print("senddata.WriteInt => " + senddata.WriteInt(data2.Length));
    print("senddata.WriteBytes => " + senddata.WriteBytes(nb));
    print("m_clientDrive.EndSend => " + m_clientDrive.EndSend(senddata));
    }
    result:
    m_clientDrive.BeginSend=> 0
    senddata.WriteInt => True
    senddata.WriteBytes => False
    m_clientDrive.EndSend => -4

    new setting in client and server
    var settings = new NetworkSettings();
    settings.WithFragmentationStageParameters(payloadCapacity: 4096);
     
  6. simon-lemay-unity

    simon-lemay-unity

    Unity Technologies

    Joined:
    Jul 19, 2021
    Posts:
    441
    You're trying to send an image of size 823KB when the capacity of your fragmentation pipeline is 4KB. Also be aware that at that size you will not be able to send that image using a pipeline that is both fragmented and reliable (the limit is roughly 88KB for those).

    As I mentioned above, Unity Transport is not designed for this kind of use case. I suggest looking at ways to avoid sending images with it. If transferring images is absolutely required for your game, you could for example serve them over HTTP and have clients download them using regular .NET APIs.
     
  7. Farshadfarzan368

    Farshadfarzan368

    Joined:
    Sep 10, 2022
    Posts:
    73
    I tested again with 55 kb image, and it doesn't work
    result:
    m_clientDrive.BeginSend=> 0
    senddata.WriteInt => True
    senddata.WriteBytes => False
    m_clientDrive.EndSend => -4
    ===================
    How do I send 20 mb? Its capacity is announced in the link above as 20 mb
     
  8. simon-lemay-unity

    simon-lemay-unity

    Unity Technologies

    Joined:
    Jul 19, 2021
    Posts:
    441
    To reach that stated capacity your pipeline must not include the
    ReliableSequencedPipelineStage
    , and you must configure the
    payloadCapacity
    parameter accordingly.
     
  9. Farshadfarzan368

    Farshadfarzan368

    Joined:
    Sep 10, 2022
    Posts:
    73
    new setting
    server:

    var settings = new NetworkSettings();
    settings.WithFragmentationStageParameters(payloadCapacity: 10000);
    m_serverDrive = NetworkDriver.Create(settings);
    _fragmentedPipeline = m_serverDrive.CreatePipeline(typeof(FragmentationPipelineStage), typeof(UnreliableSequencedPipelineStage));
    var addr = NetworkEndPoint.AnyIpv4;
    addr.Port = 8008;
    client:
    var settings = new NetworkSettings();
    settings.WithFragmentationStageParameters(payloadCapacity: 10000);
    m_clientDrive = NetworkDriver.Create(settings);
    _fragmentedPipeline = m_clientDrive.CreatePipeline(typeof(FragmentationPipelineStage), typeof(UnreliableSequencedPipelineStage));
    serverEndPoint = NetworkEndPoint.Parse("127.0.0.1", 8008);
    m_clientToServerConnection = m_clientDrive.Connect(serverEndPoint);

    result:
    m_clientDrive.BeginSend=> 0
    senddata.WriteInt => True
    senddata.WriteBytes => False
    m_clientDrive.EndSend => -4
    ===================
     
  10. Farshadfarzan368

    Farshadfarzan368

    Joined:
    Sep 10, 2022
    Posts:
    73
    new setting
    server:

    var settings = new NetworkSettings();
    settings.WithFragmentationStageParameters(payloadCapacity: 80000);
    m_serverDrive = NetworkDriver.Create(settings);
    _fragmentedPipeline = m_serverDrive.CreatePipeline(typeof(FragmentationPipelineStage));
    var addr = NetworkEndPoint.AnyIpv4;
    addr.Port = 8008;
    client:
    var settings = new NetworkSettings();
    settings.WithFragmentationStageParameters(payloadCapacity: 80000);
    m_clientDrive = NetworkDriver.Create(settings);
    _fragmentedPipeline = m_clientDrive.CreatePipeline(typeof(FragmentationPipelineStage));
    serverEndPoint = NetworkEndPoint.Parse("127.0.0.1", 8008);
    m_clientToServerConnection = m_clientDrive.Connect(serverEndPoint);

    result:

    m_clientDrive.BeginSend=> 0
    senddata.WriteInt => True
    senddata.WriteBytes => True
    m_clientDrive.EndSend => 53915
    ddddddddddddddddzzz53911
    work
     
  11. Farshadfarzan368

    Farshadfarzan368

    Joined:
    Sep 10, 2022
    Posts:
    73
    I noticed that the FragmentationPipelineStage system does not work for me,Although I selected the FragmentationPipelineStage, it is stuck in ReliableSequencedPipelineStage

    my transpot version 1.3.1;
    unity lts 2021,3,18f1
     
  12. Farshadfarzan368

    Farshadfarzan368

    Joined:
    Sep 10, 2022
    Posts:
    73
    Hello, my problem is not solved yet, thanks
    Thank you if you solve it