Search Unity

Wrong or disorted Texture in build standalone, when using Resources.Load()

Discussion in 'Scripting' started by iCreatio, Nov 17, 2016.

  1. iCreatio

    iCreatio

    Joined:
    Nov 16, 2016
    Posts:
    12
    Hello everyone,
    I have a problem with my project, when i created it and built a .exe for standalone game it works different. In unity editor it works as it have to but in standalone build it dont work corectly.

    Application:
    Map browser - creating a map from lots of .JPGs witch are sorted by speciffed name.
    Creating a terrain, creating terraindata with loaded texture, in unity editor it works perfectly, all textures are at thier places, but in standalone build some textures are ok, but almost half of them are at wrong places and some of them are disorted.

    My question is :why Resources.Load() loads wrong texture in .exe standalone, when in unityeditor it works great?? In unity editor it loads correct texture, but in standalone game it often loads a texture even from a different folder !! ( folders are in resources folder)
    For example:
    Resources:

    xxx:
    xxxyyyy
    zzz:
    zzzcccc
    zzzkkk
    where xxx and zzz are folders name and a part of texture file name which is in this folder, xxxyyyy, zzzcccc and zzzkkk are textures names


    Code:
    Code (CSharp):
    1. for (int i = 0; i < ilosc; i++) {
    2.             Terrain_data_list.Add (new List<TerrainData> ());
    3.             Terrains_list.Add (new List<GameObject> ());
    4.             for (int j = 0; j < ilosc *1.5f; j++) {
    5.          
    6.                Terrain_data_list[i].Add ( new TerrainData());
    7.                 Terrain_data_list[i][j].heightmapResolution = 1;
    8.                 Terrain_data_list[i][j].size = new Vector3 (15, 1, 15);
    9.                 Terrain_data_list[i][j].baseMapResolution =256;
    10.                 SplatPrototype[] tekstura= new SplatPrototype [1];
    11.                 tekstura [0] = new SplatPrototype ();
    12.                 string path = kamera_sterowanie.skalowanie + @"/" + kamera_sterowanie.skalowanie + indeks_na_tekst(Oblicz_indeks(poczatek) + j + i * ilosc_kolumn);
    13.  
    14.                 tekstura [0].texture = Resources.Load (path) as Texture2D;
    15.              
    16.                 Terrain_data_list[i][j].splatPrototypes = tekstura;
    17.  
    18.                 Terrains_list[i].Add(new GameObject("teren "+i.ToString()+"x"+j.ToString()));
    19.  
    20.                 Terrains_list[i][j].AddComponent<Terrain>();
    21.                 Terrains_list[i][j].gameObject.GetComponent<Terrain>().terrainData = Terrain_data_list[i][j];
    22.              
    23.                 Terrains_list[i][j].transform.position = new Vector3 (-ilosc/2*Rozmiar + j*Rozmiar, wysokosc_terenu, -ilosc/2*Rozmiar + i*Rozmiar);
    24.              
    25.             }
    26.  
    27.         }

    where function Oblicz_indeks() calculates what file should be loaded
    Kamera_sterowanie_skalowanie is a name of a direcotry where texture is and its first letters of texture name, for example: i have texture named xxxyyyy which is in directory xxx,
    where xxx is scale of the map and yyyy is a name which determines the location of texture (map fragment)(in latitude and longitude coordinates)

    n a logfile i have a message: failed to get pixels of splat texture
     
    Last edited: Nov 22, 2016
  2. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Try to reduce the problem. Is it really a problem with Resources.Load, or is it some problem with rendering of the terrain? You can't tell, because there's too much going on.

    Try to isolate a single texture that loads differently in built app vs. editor. Use lots of Debug.Logs to verify exactly what is being loaded. Then you can look for things like, have you got two different versions of that texture in two different Resources folders, etc.
     
  3. iCreatio

    iCreatio

    Joined:
    Nov 16, 2016
    Posts:
    12
    In a logfile i have a message: failed to get pixels of splat texture.
    Im thinking about change texture type to advenced and then check the parmameter: Write/Read enabled, but when i have more than 2Gbs of JPGs it will take about 2hours or more to reimport textures to unityeditor, any way im will try it
     
  4. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Ah, well yes, you must have Read/Write enabled on your textures in order to get the pixels of them.

    But no need to do all your images at once... make a simpler test case that just tries to work with one specific texture, get that working, and then fix up the rest of the images.
     
  5. iCreatio

    iCreatio

    Joined:
    Nov 16, 2016
    Posts:
    12
    No it still dont works... Now the textures are just white and in logfile is message: TerrainData is missing splat texture 0.
     
  6. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Then break it down, as I suggested before. Use lots of Debug.Logs so you can work out exactly what's happening at each step. Isolate the step where it fails to do what you think it should do.
     
  7. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    FWIW you can make a debug build and attach Visual Studio's debugger to it so you can literally step through the code line by line.

    I also don't believe that what you posted is your actual code because on lines 2 and 3 you add a new list to an existing list and then later you add single TerrainData and GameObject instances to the same lists.
     
    JoeStrout likes this.
  8. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Or MonoDevelop. Whichever you have available and prefer to use.

    This is indeed how I'd tackle it, but I don't often recommend it to newbies, because learning to use the debugger feels like an extra hurdle when you're already in a confused state... but please try it and let us know how it goes!
     
  9. iCreatio

    iCreatio

    Joined:
    Nov 16, 2016
    Posts:
    12
    Oh yes, when Im pasted my code i changed names of variables because they were in polish and i deleted [x] array indexs (by the accident), beacuse its a list of lists of terrain data and gameobjects. (Im gonna edit my post and correct code).

    I have created a delvelop build and attached it to visal studio what i have discovered is that a name (path) to the file that i want to load is correct, but unity don't find it and the result is NULL. Maybe unity trying to find it in wrong Resources folder or for some reason unity can't create a texture from a loaded file, but i think it shouldn't be null in that case? How can I get the path of resources folder that Im trying to load textures from? Soo the problem is in Resources.Load().

    After use Application.dataPath Im know the resources folder is in applicationdata folder, but i cant look inside that, beacuse its a .asset file, and i can't examine a textures.

    Strage is that it have loaded a textures (wrong and disorted, but anyway loaded it) but after i changed textture type to advenced and enabled Read/Write, application don't load (find?) the textures. In unityeditor it works great but in build it can't find/load the textures.
     
    Last edited: Nov 22, 2016
  10. iCreatio

    iCreatio

    Joined:
    Nov 16, 2016
    Posts:
    12
    I solved this by loading a texture from bytes:
    Code (CSharp):
    1. sciezka2 = Application.dataPath;
    2.                 string sciezka = kamera_sterowanie.skalowanie + @"\" + kamera_sterowanie.skalowanie + indeks_na_tekst(Oblicz_indeks(poczatek) + j + i * ilosc_kolumn);
    3.                 byte[] dane_z_pliku;
    4.                 //tekstura [0].texture = Resources.Load (sciezka) as Texture2D;
    5.                 if (File.Exists(sciezka2 + "/Resources/" + sciezka + ".JPG"))
    6.                 {
    7.                     dane_z_pliku = File.ReadAllBytes(sciezka2 + "/Resources/" + sciezka + ".JPG");
    8.                     tekstura[0].texture = new Texture2D(2, 2);
    9.                     tekstura[0].texture.LoadImage(dane_z_pliku);
    10.                 }
    11.                 else if (File.Exists(sciezka2 + "/Resources/pusty.JPG"))
    12.                 {
    13.                     dane_z_pliku = File.ReadAllBytes(sciezka2 + "/Resources/pusty.JPG");
    14.                     tekstura[0].texture = new Texture2D(2, 2);
    15.                     tekstura[0].texture.LoadImage(dane_z_pliku);
    16.                 }
    17.                 Debug.Log("Loading texture: " + sciezka + "   textura: ", tekstura[0].texture);
    18.              
    19.                 Dane_terenu_wiersze[i][j].splatPrototypes = tekstura;
    20.  
    21.                 Teren_wiersze[i].Add(new GameObject("teren "+i.ToString()+"x"+j.ToString()));
    22.  
    23.                 Teren_wiersze[i][j].AddComponent<Terrain>();
    24.                 Teren_wiersze[i][j].gameObject.GetComponent<Terrain>().terrainData = Dane_terenu_wiersze[i][j];
    25.              
    26.                 Teren_wiersze[i][j].transform.position = new Vector3 (-ilosc/2*Rozmiar + j*Rozmiar, wysokosc_terenu, -ilosc/2*Rozmiar + i*Rozmiar);
    Anyway Im still don't know why it don't works from Resources.Load() and it would be good to know it in the future.
     
    Last edited: Nov 30, 2016
  11. iCreatio

    iCreatio

    Joined:
    Nov 16, 2016
    Posts:
    12
    Update.
    Still having same problem but now whend using Resources.Load() to load terraindata
     
  12. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    All this makes it sound rather like you believe resource paths are file paths, and resources are files. They're not. A resource path is a path in your project hierarchy, based on a folder called (exactly) Resources. And the assets within are not files; they're assets, which get combined and compiled out to some opaque format we shouldn't care about.

    So, yeah, if you're taking a resource path and somehow mucking with it enough to find the actual file, this will work in the editor because you're accessing the source file in your project. But it won't work at runtime because that file doesn't exist.

    So I think it's time to back up and reconsider your life choices. :) Quit thinking of (and treating) resources as files. All you can do with a resource path is Resources.Load it; any attempt to deal with it as a file (unless you're writing some sort of editor extension) is going to fail.
     
    KelsoMRK likes this.
  13. iCreatio

    iCreatio

    Joined:
    Nov 16, 2016
    Posts:
    12
    Ok, now I understand, so after building a standalone all used files are converted to assets, Im reference to them by a path when they are real files in my project. How can I get reference to them after I build a standalone and they are compressed assets?
    Im going to convert(package) all my data to assetbundle and later, after I build a standalone Im will use that assetbundle to load my textures, terraindata and other objects, for this moment I don't see other way.

    Thanks for answer and helping me understanding Unity resources/asset structure.
     
  14. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    The "paths" are local to the Resources folder. So if you have a texture in your project in /Assets/Resources/textures/foo.png then you'd use Load with "textures/foo" as the path argument
     
    JoeStrout likes this.
  15. iCreatio

    iCreatio

    Joined:
    Nov 16, 2016
    Posts:
    12
    I'm using the path argument excatlly that way. Im have a folder named "500" in Resources folder in my project: "Projectdirectory/Assets/Resources/500" In this folder I have for example texture named "500123AD011.png", now to load this texture i call Resources.Load("500/500123AD011") as Texture2D and I get a texture as a result while in editor but in build the result is NULL.
     
  16. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Please show simple code that demonstrates this problem. It should take no more than 2 or 3 lines.

    I'm asking for this because I suspect the texture is not null, but something you're doing with it is producing null (for example because the texture is not marked as Writeable, and you're trying to do something like get its pixels). So, just call Resources.Load("500/500123AD011") and then immediately check and DebugLog the result.

    (FYI, I use Resources.Load this way in High Frontier and it's working fine for me.)
     
  17. iCreatio

    iCreatio

    Joined:
    Nov 16, 2016
    Posts:
    12
    I think Im couldn't load textures beacuse Resources folder were to big, Im tried to use a AssetBundles and its working great :) Im think a Resources folder have limit of its size