- Home /
Sending texture updates from client to server
I'm working on a multiplayer sample wherein player's can see each other while playing. Currently, I just want to send the updated webcam video as png images over the network (will worry about compression/encoding later). I'm unsure how to accomplish this.
Initially, I thought I'd have a component attached to my player prefab, say PlayerVideo
that overrides the OnSerialize
and OnDeserialize
methods -- however, these functions seem to be for the server to send specific updates to the clients (i.e., your own SyncVar
functionality)
It seemed like Commands
and ClientRPC
calls are what I needed. The flow being:
PlayerVideo.Update() --> GetWebCamFeed() --> SendToServer --> CmdVideoTextureUpdate --> RpcUpdateVideoTexture
How do I send these texture data to the server and from the server to the clients though? I don't understand how exactly to use NetworkWriter
and NetworkReader
to accomplish this.
Here's some code:
void Update()
{
// Send server the updated video texture data as a NetworkWriter object
if (isLocalPlayer)
{
byte[] textureData = m_playerVideoTexture.EncodeToPNG();
NetworkWriter writer = new NetworkWriter();
writer.WriteBytesFull(textureData);
CmdVideoTextureUpdate(writer);
}
}
[Command]
void CmdVideoTextureUpdate(NetworkWriter writer)
{
// argument should be NetworkReader, instead it's writer.. how to fix?
RpcUpdateVideoTexture(textureData);
}
[ClientRpc]
void RpcUpdateVideoTexture(NetworkReader reader)
{
if (isLocalPlayer)
return;
byte[] textureData = reader.ReadBytesAndSize();
m_playerVideoTexture.LoadImage(textureData);
m_playerVideoTexture.Apply();
}
How do I convert the NetworkWriter
object to a NetworkReader
object for the clientrpc to use? Or is this just the wrong way to do this in the first place?
Answer by seanr · Jul 22, 2015 at 05:20 PM
you could use NetworkWriter.ToArray() and send the array of bytes, then construct a NetworkReader from the array of bytes.
Thanks for helping out Sean! I didn't quite get what you meant. Can a command/clientrpc have a byte[]
argument (and Unity takes care of serializing it and sending it down as a message)? i.e.
[Command]
void CmdVideoTextureUpdate(byte[] data) {
RpcUpdateVideoTexture(data);
}
[ClientRpc]
void RpcUpdateVideoTexture(byte[] data)
{
if (isLocalPlayer)
return;
m_playerVideoTexture.LoadImage(data);
m_playerVideoTexture.Apply();
}
If I send a network message with the data, I'd have to route the data to the right network object. Is that correct?
Thanks @seanr, so I tried it and it seems like the PNG encoded texture byte data (haven't added video encoding yet) is too large.
UnityException: NetworkWriter used buffer is too big!
UnityEngine.Networking.NetworkServer.SendWriterToReady (UnityEngine.GameObject contextObj, UnityEngine.Networking.NetworkWriter writer, Int32 channelId) (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkServer.cs:333)
Is there something I can do to work around it? Or would message passing be the alternative (with messages, it seems like i'd have to have a global client message handler and have to do a per-player-texture-data-sync manually)
there is a limit of (about) 1400 bytes on regular messages. If you use a fragmented channel, the limit is 32$$anonymous$$. You would add a fragmented channel to the QoS channels in the Network$$anonymous$$anager settings, then use [Command(channel=3)] where 3 is the new channel index.
Your answer
Follow this Question
Related Questions
Networking physics with HLAPI 1 Answer
Unity networking tutorial? 6 Answers
Need help getting "Server Reconciliation" to work. 0 Answers
How to watch in client applications what it is happening in the server one? 0 Answers
Creating a multiplayer game. 1 Answer