Search Unity

UnityWebRequestTexture

Discussion in 'Scripting' started by btckey, Mar 21, 2021.

  1. btckey

    btckey

    Joined:
    Nov 1, 2012
    Posts:
    40
    Good evening.

    1) I want to load texture via UnityWebRequestTexture
    2) Add texture to variable
    3) Use texture from other scripts

    What am I doing.
    I have a LoaderTextures script a texture loader with url
    In this script, I load the texture Сoncrete_1.png and add the value to the public variable Сoncrete

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.Networking;
    4.  
    5. public class LoaderTextures : MonoBehaviour
    6. {
    7.         public Texture concrete;
    8.  
    9.         void Start()
    10.         {
    11.              StartCoroutine(LoadTexture());
    12.         }
    13.  
    14.         IEnumerator LoadTexture()
    15.         {
    16.                 using (UnityWebRequest uwr = UnityWebRequestTexture.GetTexture("file:///C:/Games/Textures/Concrete_1.png"))
    17.                 {
    18.                         yield return uwr.SendWebRequest();
    19.  
    20.                         if(uwr.isNetworkError || uwr.isHttpError)
    21.                         {
    22.                             Debug.Log(uwr.error);
    23.                         }
    24.                         else
    25.                         {
    26.                             concrete = DownloadHandlerTexture.GetContent(uwr);
    27.                         }
    28.                 }
    29.         }
    30. }
    31.  
    Next, from another script, I refer to the concrete variable and it gives me null

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class LoaderObjects : MonoBehaviour
    5. {
    6.         private LoaderTextures tex;
    7.  
    8.     void Start()
    9.     {
    10.         tex= GameObject.Find("LoaderTextures").GetComponent<LoaderTextures>();
    11.    
    12.         Debug.Log(tex.сoncrete);
    13.     }
    14. }
    How can I load a texture and then use it in a scene?
    In the inspector, the concrete variable has a value with a loaded texture, but I can't take it, what am I doing wrong
     
    Last edited: Mar 21, 2021
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,686
    First thing I would investigate is that URL. Give it a "normal" URL out on the internet somewhere, or just use a local http server and load it.

    We know that texture loading works (see examples in UnityWebRequest docs) so start with a "normal" URL and then work up to whether Windows will even know how to handle all that
    file:///c:/
    magic.

    That URL might be correct, but it might not. Isolate if what you're seeing is the mechanism, or just the bad URL.
     
  3. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,909
    There is an example of how to use UnityWebrequestTexture here: https://docs.unity3d.com/ScriptReference/Networking.UnityWebRequestTexture.GetTexture.html

    Note that this is a network request, which is why the example is starting a coroutine which waits for the image to be downloaded from the URL. It will not be available immediately.

    I notice you are trying to read the texture from Start() in another script. The issue is that you aren't waiting for the texture to finish downloading and be assigned. So most likely, it is simply not ready yet.

    A couple ways to deal with this off the top of my head:
    • Keep checking if the texture is loaded each frame in Update
    • Have your LoaderTextures class expose a C# event to notify other classes when the texture is finished loading.
     
    Kurt-Dekker likes this.
  4. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,731
    Coroutine runs during Update, so if both scripts are in the same scene and both are enabled, the texture will be null during Start.
     
  5. btckey

    btckey

    Joined:
    Nov 1, 2012
    Posts:
    40
    I understood you, yesterday I tried for a long time options on how this can be done, everything worked out for me thanks to your help.

    But now I decided to combine 3 scripts together in one file to optimize the process.

    I have 3 IEnumerators.
    How can I make it so that LoadTexture () is executed first; then LoaderNormal (); and LoaderObject ();

    1) LoadTexture (); // Done completely goes to LoaderNormal ();
    2) LoaderNormal (); // Done completely jumps to LoaderObject ();
    3) LoaderObject ();

    Code (CSharp):
    1.     void Start()
    2.     {
    3.         StartCoroutine(LoadTexture();// Done completely goes to LoaderNormal ();
    4.         StartCoroutine(LoaderNormal();// Done completely jumps to LoaderObject ();
    5.         StartCoroutine(LoaderObject();
    6.     }
    7.  
    8.     IEnumerator LoadTexture()
    9.     {
    10.         Debug.Log(0);
    11.     }
    12.  
    13.     IEnumerator LoaderNormal()
    14.     {
    15.         Debug.Log(1);
    16.     }
    17.  
    18.     IEnumerator LoaderObject()
    19.     {
    20.         Debug.Log(2);    
    21.     }
    I am not very good at C # and its features as it is not my native language, but I can read it.
    I really like Unity3D, I am learning more and more and it is very exciting. :)

    For the code with an example in C #, I would like to separately thank you.
     
  6. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,731
    The way you wrote you ask them to execute at the same time. If you want LoaderNormal to execute after LoadTexture, then put StartCoroutine(LoaderNormal()); into LoadTexture() at the point where texture is already loaded. Solve the third one likewise.
     
  7. btckey

    btckey

    Joined:
    Nov 1, 2012
    Posts:
    40
    I am very sorry to Aurimas-Cernius that this does not work for me
    I very carelessly wrote the code, cutting down all the unnecessary previously written by me.
    I didn't think that for(); will be important.

    Here's a sample code where it doesn't work as expected. It won't be right.
    There will be repetitions

    Code (CSharp):
    1.     private string[] nameTexture = {"Texture_1","Texture_2"};
    2.     private string[] nameNormal = {"Normal_1","Normal_2"};
    3.     private string[] nameObject = {"Object_1","Object_2"};
    4.  
    5.     void Start()
    6.     {
    7.      
    8.         for(int i = 0; i < nameTexture.Length; i++)
    9.         {
    10.             StartCoroutine(LoadTexture(nameTexture[i]));
    11.         }
    12.  
    13.         for(int i = 0; i < nameNormal.Length; i++)
    14.         {
    15.             StartCoroutine(LoaderNormal(nameNormal[i]));
    16.         }
    17.      
    18.         for(int i = 0; i < nameObject.Length; i++)
    19.         {
    20.             StartCoroutine(LoaderObject(nameObject[i]));
    21.         }
    22.     }
     
  8. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,731
    This code create a lot of coroutines which then all run at the same time. Like I said, your Start should only start coroutines which have no dependencies. The dependencies have to started from inside the coroutines when everything is already loaded.
     
  9. btckey

    btckey

    Joined:
    Nov 1, 2012
    Posts:
    40
    The point is that if I put LoadTexture in nameNormal.
    LoadTexture will be executed twice as there are 2 values in the nameNormal array

    Code (CSharp):
    1.     private string[] nameTexture = {"Texture_1","Texture_2"};
    2.     private string[] nameNormal = {"Normal_1","Normal_2"};
    3.     private string[] nameObject = {"Object_1","Object_2"};
    4.  
    5.     void Start()
    6.     {
    7.  
    8.         for(int i = 0; i < nameTexture.Length; i++)
    9.         {
    10.             StartCoroutine(LoadTexture(nameTexture[i]));
    11.         }
    12.     }
    13.  
    14.     IEnumerator LoadTexture(string nameTexture)
    15.     {
    16.         // First run code nameTexture
    17.      
    18.  
    19.         for(int i = 0; i < nameNormal.Length; i++)
    20.         {
    21.             StartCoroutine(LoaderNormal(nameNormal[i]));
    22.         }
    23.     }
    24.  
    25.     IEnumerator LoaderNormal(string nameObject)
    26.     {
    27.         // Second run code nameNormal
    28.      
    29.         for(int i = 0; i < nameObject.Length; i++)
    30.         {
    31.             StartCoroutine(LoaderObject(nameObject[i]));
    32.         }
    33.     }
    34.  
    35.     IEnumerator LoaderObject(string nameObject)
    36.     {
    37.         // Third execution code nameObject
    38.     }
    39.  
     
    Last edited: Mar 22, 2021