Search Unity

Trying to load a texture but getting overread error

Discussion in 'Scripting' started by kenmarold, Oct 30, 2017.

  1. kenmarold

    kenmarold

    Joined:
    Jun 11, 2015
    Posts:
    27
    I feel like I'm doing everything by the book here so I'm at a loss for as to why this is happening. I'm passing a byte array over the network from client to server and then reading those bytes back in as a collection of variables. One of the variables, a Texture2D, I'm converting to bytes before sending using GetRawTextureData() and then trying to load it back in once received using LoadRawTextureData(). But there is an error throw. at `tex.LoadRawTextureData(texBytes);` that I feel like I've addressed but is still occurring.

    Everything I've found online regarding this error points to specifing more information to let Unity know what kind of Texture that is constructing from the raw byte array, so I've included everything `Texture2D tex = new Texture2D(texWidth, texHeight, TextureFormat.RGBA32, false);` but it is still generating the error. I've included the full script below, but the error is occuring in the coroutine `IEnumerator DoApplyTex();` on the line `tex.LoadRawTextureData(texBytes);`. What's going wrong here?

    Code (CSharp):
    1.     using System.Collections;
    2.     using UnityEngine;
    3.     using UnityEngine.Networking;
    4.     using UnityEngine.UI;
    5.  
    6.     public class Player_Data
    7.     {
    8.         public byte[] texBytes;
    9.         public int texWidth;
    10.         public int texHeight;
    11.  
    12.         public Vector3 location;
    13.         public string type;
    14.         public string id;
    15.         public int strength;
    16.         public int hitpoints;
    17.     }
    18.  
    19.     public class Player_Controller : NetworkBehaviour
    20.     {
    21.         Player_Data playerData = new Player_Data();
    22.  
    23.         public GameObject clientAvatar;
    24.         public GameObject serverAvatar;
    25.  
    26.         public Texture2D texToSend;
    27.         string typeToSend = "Deer";
    28.         public string idToSend { get; set; }
    29.         int strengthToSend = 80;
    30.         int hitPointsToSend = 2;
    31.  
    32.         public override void OnStartLocalPlayer()
    33.         {
    34.             PrepareData();
    35.         }
    36.  
    37.         [Client]
    38.         void InstantiateClientAvator()
    39.         {
    40.             Instantiate(clientAvatar);
    41.  
    42.             Renderer avatarRend;
    43.             avatarRend = clientAvatar.GetComponent<Renderer>();
    44.             avatarRend.sharedMaterial.mainTexture = texToSend;
    45.         }
    46.  
    47.         [Client]
    48.         void PrepareData()
    49.         {
    50.             Player_ID id = GetComponent<Player_ID>();
    51.             Player_Spawn spawn = GetComponent<Player_Spawn>();
    52.  
    53.             StartCoroutine(DoGetRawTextureData(texToSend));
    54.  
    55.             playerData.texWidth = texToSend.width;
    56.             playerData.texHeight = texToSend.height;
    57.             playerData.location = spawn.GetPlayerPos();
    58.             playerData.type = typeToSend;
    59.             playerData.id = id.MakeUniqueIdentity();
    60.             playerData.strength = strengthToSend;
    61.             playerData.hitpoints = hitPointsToSend;
    62.  
    63.             SendData(playerData);
    64.         }
    65.         IEnumerator DoGetRawTextureData(Texture2D tex)
    66.         {
    67.             playerData.texBytes = texToSend.GetRawTextureData();
    68.  
    69.             yield return new WaitForEndOfFrame();
    70.  
    71.             GameObject infoDisplayText = GameObject.Find("InfoDisplay");
    72.             infoDisplayText.GetComponent<Text>().text += "Bytes to send : " + playerData.texBytes.Length + "\n";
    73.         }
    74.  
    75.         // Send Client player data to server
    76.  
    77.         [Client]
    78.         void SendData(Player_Data data)
    79.         {
    80.             CmdInstantiatePlayerOnServer(data);
    81.             CmdInstantiatePlayerOnClient(data);
    82.             CmdShowClientDataOnServer(data);
    83.         }
    84.  
    85.         [Client]
    86.         void CmdInstantiatePlayerOnClient(Player_Data data)
    87.         {
    88.             GameObject go = Instantiate(clientAvatar);
    89.  
    90.             StartCoroutine(DoApplyTex(go, data.texBytes, data.texWidth, data.texHeight));
    91.         }
    92.  
    93.         [Command(channel = 2)]
    94.         void CmdInstantiatePlayerOnServer(Player_Data data)
    95.         {
    96.             GameObject go = Instantiate(serverAvatar);
    97.  
    98.             StartCoroutine(DoApplyTex(go, data.texBytes, data.texWidth, data.texHeight));
    99.         }
    100.  
    101.         IEnumerator DoApplyTex(GameObject go, byte[] texBytes, int texWidth, int texHeight)
    102.         {
    103.             Texture2D tex = new Texture2D(texWidth, texHeight, TextureFormat.RGBA32, false);
    104.             tex.LoadRawTextureData(texBytes);
    105.             tex.Apply();
    106.             yield return new WaitForEndOfFrame();
    107.             go.GetComponent<Renderer>().material.mainTexture = tex;
    108.         }
    109.  
    110.         [Command(channel = 2)]
    111.         void CmdShowClientDataOnServer(Player_Data data)
    112.         {
    113.             GameObject infoDisplayText = GameObject.Find("InfoDisplay");
    114.             infoDisplayText.GetComponent<Text>().text += "Image Size : " + data.texBytes.Length.ToString() + "\n";
    115.             infoDisplayText.GetComponent<Text>().text += "Image Width : " + data.texWidth.ToString() + "\n";
    116.             infoDisplayText.GetComponent<Text>().text += "Image Height : " + data.texHeight.ToString() + "\n";
    117.             infoDisplayText.GetComponent<Text>().text += "Player Location : " + data.location.ToString() + "\n";
    118.             infoDisplayText.GetComponent<Text>().text += "Player Type : " + data.type + "\n";
    119.             infoDisplayText.GetComponent<Text>().text += "Player ID : " + data.id + "\n";
    120.             infoDisplayText.GetComponent<Text>().text += "Player Strength : " + data.strength + "\n";
    121.             infoDisplayText.GetComponent<Text>().text += "Player Hit Points : " + data.hitpoints + "\n";
    122.  
    123.             RpcDataReceivedConfirmation("Data Received by Server");
    124.         }
    125.  
    126.         // Show Server Confimration on Client InfoDisplay
    127.  
    128.         [ClientRpc]
    129.         void RpcDataReceivedConfirmation(string data)
    130.         {
    131.             if (isLocalPlayer)
    132.             {
    133.                 GameObject infoDisplayText = GameObject.Find("InfoDisplay");
    134.                 infoDisplayText.GetComponent<Text>().text += data + "\n";
    135.             }
    136.         }
    137.     }
     
  2. nat42

    nat42

    Joined:
    Jun 10, 2017
    Posts:
    353
    What do "Image Size", "Image Width" & "Image Height" show?

    Btw seems odd to me (non-Unity hat here) that you accept data from the client without validating it
     
  3. tonemcbride

    tonemcbride

    Joined:
    Sep 7, 2010
    Posts:
    1,089
    In your 'prepare data' function you start a coroutine to get the texture data (DoGetRawTextureData). It looks like you don't wait for this to finish though before sending the data. If you move the rest of the code in 'prepare data' to the end of that coroutine that should help.
     
    kenmarold likes this.