Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Sync texture over network!

Discussion in 'Multiplayer' started by rajmond, Feb 3, 2011.

  1. rajmond

    rajmond

    Joined:
    May 18, 2010
    Posts:
    56
    Anyone knows (has the actual code) how to sync the texture of the objects?! I have an objects in the scene so when I click it I can paste the URL of a picture and it will be loaded as a texture of that object! So now I'm trying how to share that texture with clients in the network?!

    Regards,
    Rajmond
     
  2. PrimeDerektive

    PrimeDerektive

    Joined:
    Dec 13, 2009
    Posts:
    3,090
    Could you post the code you have for doing it non-networked?
     
  3. rajmond

    rajmond

    Joined:
    May 18, 2010
    Posts:
    56
    Here is the script which loads the texture:

    var url : String = "http://blog.undergroundcityxxi.org/wp-content/uploads/2010/01/gamerz_01.jpg";

    var www : WWW;
    var wwwimage : String;
    var objname : String;
    var picture : Texture2D;


    function Start () {

    while(true){
    picture= new Texture2D(4, 4, TextureFormat.RGB24, false);

    var www = new WWW(url);

    yield www;


    www.LoadImageIntoTexture(picture);
    }
    }


    function OnGUI ()
    {

    var ball2 = gameObject.Find(objname);
    url = GUI.TextField (Rect (10, 40, 500, 20), url, 500);

    if (GUI.Button (Rect (510,40,90,18), "Load Texture")) {

    ball2.renderer.material.mainTexture = new Texture2D(4, 4, TextureFormat.RGB24, false);
    ball2.renderer.material.mainTexture = picture;


    }
    }
     
  4. JRavey

    JRavey

    Joined:
    May 12, 2009
    Posts:
    2,377
    You're most of the way there, but there is no direct way to do this in Unity networking. You could serialize the texture, send it, then deserialize it on the far end. You could convert it to a string object and send it that way, but I'm not entirely sure how well that would work with Unity's RPCs. If you don't mind saving it to disk and then loading the texture back from that, it would be easier; that would not work with a web player.

    If this is for tags or something, such as those used in many FPS games, perhaps a central repository in a database would be better.
     
  5. rajmond

    rajmond

    Joined:
    May 18, 2010
    Posts:
    56
    I thought about saving to disk and load it, but updating automatically is more easy (thinking of not "advanced" users).
    I created a database (PHP MySQL) and where you can upload pictures and download into the disk, but then you had to write the link/path of that picture in the unity textfield so then it would be loaded as the texture! It's a bit time demanding and nor really nice :(!
     
  6. PrimeDerektive

    PrimeDerektive

    Joined:
    Dec 13, 2009
    Posts:
    3,090
    Please use code tags in the future. Anyway, I would probably do something like this:

    Code (csharp):
    1. var url : String = "http://blog.undergroundcityxxi.org/wp-content/uploads/2010/01/gamerz_01.jpg";
    2.  
    3. var www : WWW;
    4. var wwwimage : String;
    5. var objname : String;
    6. var picture : Texture2D;
    7.  
    8.  
    9. function Start () {
    10.  
    11.     while(true){
    12.         picture= new Texture2D(4, 4, TextureFormat.RGB24, false);
    13.         var www = new WWW(url);
    14.         yield www;
    15.         [url]www.LoadImageIntoTexture(picture);[/url]
    16.     }
    17.    
    18. }
    19.  
    20.  
    21. function OnGUI ()
    22. {
    23.     var ball2 = gameObject.Find(objname);
    24.     url = GUI.TextField (Rect (10, 40, 500, 20), url, 500);
    25.  
    26.     if (GUI.Button (Rect (510,40,90,18), "Load Texture")) {
    27.         SetNewTexture();
    28.         networkView.RPC ("SetNewTexture", RPCMode.Others);
    29.  
    30.     }
    31.    
    32. }
    33.  
    34. @RPC
    35. function SetNewTexture(){
    36.     ball2.renderer.material.mainTexture = new Texture2D(4, 4, TextureFormat.RGB24, false);
    37.     ball2.renderer.material.mainTexture = picture;
    38. }
    Do you mean syncing the URL, or just syncing the setting of the texture on the ball?
     
  7. MikeHergaarden

    MikeHergaarden

    Joined:
    Mar 9, 2008
    Posts:
    1,027
    I see two easy methods:

    1) Send an RPC with the same texture link and have every client download the image from the URL.
    2) Send the image data in a byte[] to the other clients. This is perfectly possible with unity networking, I do this in Cubelands.
    I have not yet hit a limit in the byte[] length. (Strings are limited to 4096 chars but can be converted to byte[])

    However!
    Why are you using "while(true){"..this seems like a very heavy script to run: it keeps downloading and assigning the texture over and over again?
     
  8. rajmond

    rajmond

    Joined:
    May 18, 2010
    Posts:
    56
    This would update the texture of that object through the network?!
     
  9. MikeHergaarden

    MikeHergaarden

    Joined:
    Mar 9, 2008
    Posts:
    1,027
    Please be more precise, what/which method would?
    You dont need to update 'trough the network' as long as it's the same everywhere right? (Synchronized)

    But the short answer: yes.
     
  10. PrimeDerektive

    PrimeDerektive

    Joined:
    Dec 13, 2009
    Posts:
    3,090
    He's using a direct example from the scripting reference. I'm pretty sure its designed to constantly update, so in the event that the image on the server changes, the texture changes. (The example in the doc's is using the url of snapshots from a camera that regularly change in front of a TGI Friday's, lol).
     
  11. MikeHergaarden

    MikeHergaarden

    Joined:
    Mar 9, 2008
    Posts:
    1,027
    Ah that's why. The docs example is fine, but in this case it's way too heavy on CPU and bandwidth.
     
  12. rajmond

    rajmond

    Joined:
    May 18, 2010
    Posts:
    56
    This was mentioned to legend411 to his last post!

    And Leepo, the second suggestion of your is what I need (at least I think). Could you please send me the code, as I don't know how to do it?!
    And I use the while loop so I can update the link of the texture during game play as well, as the function Start() happens just once!
     
  13. PrimeDerektive

    PrimeDerektive

    Joined:
    Dec 13, 2009
    Posts:
    3,090
    Assuming the other instances of this object in the other players' games were running the same script (and therefore, have the same URL set for the www), then yes, the code I posted should work, although I didn't test it or anything. If you changed the URL though, you'd have to set up an RPC to change it for the other players, too.

    All the code I posted is doing is sending a message to all players to change the ball texture to the texture from that URL, so if all players are running the same script and updating the texture in in Start() from the same URL, then it should work.
     
  14. Claude23

    Claude23

    Joined:
    Aug 6, 2011
    Posts:
    4
    Is it possible to download a texture from url using WWW class only when a new version is available? As mentioned before, downloading and assigning the texture using while(true) would be not desirable and very heavy in most situations.
     
  15. cerebrate

    cerebrate

    Joined:
    Jan 8, 2010
    Posts:
    261
    yes. I do that actually, but you can't use WWW (doesn't support GETs with modified headers), and the server also needs to support the "If-Modified-Since" header.

    Code (csharp):
    1.  
    2.                //----------check the modification date/time of this file on the server-------
    3.                //get the last write time of the locally saved file
    4.                 var lastWriteTime = File.GetLastWriteTimeUtc(localFilePath);
    5.  
    6.                 //Debug.Log("Sending request to check for new version of image");
    7.                 var r = new HTTP.Request("get", WEB_IMAGE_LOCATION + filename);
    8.                 r.AddHeader("IF-Modified-Since", Rfc822DateTime.ToString(lastWriteTime));
    9.                 r.Send();
    10.  
    11.                 while (!r.isDone)
    12.                 {
    13.                     yield return null; //we're not done, so skip to the next frame.
    14.                 }
    15.  
    16.                 //we should get a 304 if the file is not modified
    17.                 //Debug.Log("got response " + r.response.message + " size: " + r.response.bytes.Length);
    18.  
    19.                 if (r.response.message == "OK") //the image has changed
    20.                 {
    21.                     //we have the bytes of the image now. Load it into the texture.
    22.  
    23.                     var saveTexture = new Texture2D(256, 256, TextureFormat.ARGB32, true);
    24.                     saveTexture.wrapMode = TextureWrapMode.Clamp;
    25.  
    26.                     saveTexture.LoadImage(r.response.bytes);
    27.  
    28.                     // some other stuff.....
    29.                  }
    30.                  else
    31.                  {
    32.                     //file is up to date, or it doesn't exist, or something
    33.                  }
    34.  
    The attached zip has the HTTP class, with a dll dependency (Ionic Zip library), as well as the RFC822DateTime class. I did not create the http class or its dependency, or the RFC822DateTime class - I can't remember where I got them from specifically, but I went searching for similar to what you asked for

    The nice thing about using the If-Modified-Since header is that it does exactly what you asked - it returns a 304 if the file isn't modified, meaning it doesn't download the image, saving on bandwidth. If the image has changed, then it DOES download the image, meaning you don't have to make another web request to download it after checking.
     

    Attached Files: