Hello,
i’m try to figure out how to send a small png file 100-200k from Server/Client to Client and via versa.
I have this script here but it doesn’t work…
Also i never had used the Network writer before and so no idea if i’m on the right trail…
Is there a example how to send a user image over network?
If someone has a idea or know how please feel free to comment here…
many many thxx
M.
using UnityEngine;
using System.Collections;
using UnityEngine.Networking;
using UnityEngine.Networking.NetworkSystem;
public class SendTexture : NetworkBehaviour {
public Texture2D playerTexture;
public Texture2D tempTexture;
private byte[] textureData;
void Start(){
if (!isServer){
playerTexture = tempTexture;
Debug.Log(isLocalPlayer);
}
}
public void SendImage(){
byte[] textureData = playerTexture.EncodeToPNG();
NetworkWriter writer = new NetworkWriter();
writer.WriteBytesFull(textureData);
byte[] data = writer.AsArray();
CmdServerTextureUpdate(data);
}
[Command(channel=3)]
void CmdServerTextureUpdate(byte[] data) {
RpcClientTextureUpdate(data);
}
[ClientRpc]
void RpcClientTextureUpdate(byte[] data) {
playerTexture.LoadImage(data);
playerTexture.Apply();
}
Commands must have a “Cmd” in front of the method name, so “CmdTextureUpdate()” or something like that, instead. RPC calls must have an “Rpc” in front, so “RpcTextureUpdate()”
Hello,
well i narrowed the problem down…
I have now a tiny texture 2.0KB RGB < MTU1500 bytes
If i use the NetworkWriter to send the bytes something comes over but not the texture…
so if i try like this i got a ? as texture:
NetworkWriter writer = new NetworkWriter();
writer.WriteBytesFull(textureData);
byte[] data = writer.ToArray();
Texture2D receivedTexture = new Texture2D(16, 12, TextureFormat.RGB24, false);
receivedTexture.LoadImage(data);
textureObjectOriginal.GetComponent<Renderer>().material.SetTexture("_MainTex", receivedTexture);
does anyone know how to write the bytes in the correct way?
many thx
M.
I also had a lot of problems sending byte arrays over the network.
Check if your channel type is “Reliable Fragmented”
Don’t use Commands or RPCCalls for big byte arrays. I think they have a fragment size limitation which is not configurable yet. I am not sure if they fixed that, but you can try to change the values of “networkManager.connectionConfig.FragmentSize” and “networkManager.connectionConfig.MaxSentMessageQueueSize” and see if it works
As a last resort try using NetworkMessages and sending them with client.SendByChannel(messageID, message, channel).
I ended up with NetworkMessages in combination with “MaxSentMessageQueueSize = 512”. Worked fine when I sent PNGs with the size around 40kB
I just posted a thread about something else but in it there is an explanation for our file sending approach (which works with big files too). Increase Bandwidth Restriction - Unity Engine - Unity Discussions see if that helps.
Basically I’m sending messages, not using RPCs (but that doesn’t matter).
The max packet size for ReliableSequenced is 1500 bytes. Subtracting all the information like ip, timestamps and what not that’s been sent with a NetworkMessage that makes the bytes under 1400. I’m not sure if that’s the case with RPCs but it is with NetworkServer.Send and NetworkClient.Send.
ReliableSequenced however can be up to 64000 bytes big (again, less than that because of all the other information).
So if you want to send a file bigger than 64kb you will have to manually segment the file and send it.
What I have is two classes:
One for loading all sorts of files into a byte array and keeping information about the files (names, sizes, types…) - GameFile
And one for sending the files which contains methods for receiving files and getting file chunks from the file - FileTransferHandler
When sending the file I use the FileTransferHandler to get small chunks from the GameFile and send them using a ReliableSequenced channel. Basically the handler contains a byte index which holds the information about how much of the file is sent (for example if the index is 1299, then I have only sent 1300 bytes so the next chunk will start from the 1300 index and so on and so on).
Prior to sending the chunks, I send a message to the receiver telling them what type of file they are going to be receiving, the name, the size (the receiver has to know how big is this file so it knows when the files has been received) and other information. The receiver then adds an empty file to a file buffer and every time the receiver receives a chunk it feeds it to that file in the buffer until the file is complete.
Of course you need to have unique file identifiers (could be an int, could be a string) to be able to tell which byte chunk is for which received file.
Also, don’t send all of the byte chunks in one go. Send for example 10 or 20 chunks and wait for a reply from the receiver (my receiver replies on the final chunk e.g. if I send 10 chunks at a time, the receiver will reply after the tenth chunk has been received). If you send all of the chunks in one go you will clog the network.