Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Load texture from external folder at runtime

Discussion in 'Getting Started' started by Domarius, Mar 22, 2020.

  1. Domarius

    Domarius

    Joined:
    Jan 5, 2013
    Posts:
    103
    From everything I've read, I should just be able to go:
    Code (CSharp):
    1. Texture tex = Resources.Load<Texture>("my_texture");
    2. my_material.mainTexture = tex;
    For whatever reason, this just doesn't work. The material still displays the original texture it had at the start of the program.

    I've attached a minimum viable project to reproduce my situation. It's just the Assets folder and should work in a new blank 2D project. It contains 2 texture files, and the scene has a single sprite with one of the textures applied. The sprite has a script which simply tries to apply the other texture when the game starts, but the initial texture remains...
     

    Attached Files:

  2. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,630
    Resources.Load isn't what you're looking for. Here is a quote from the documentation:
    https://docs.unity3d.com/ScriptReference/Resources.html

    If you want to load a texture that isn't located in your project, you have a few different options. Here are two I've used.

    The quick way is to use ImageConversion.LoadImage:
    https://docs.unity3d.com/ScriptReference/ImageConversion.LoadImage.html

    Code (CSharp):
    1. bytes = System.IO.File.LoadAllBytes(filePath);
    2. texture = new Texture2D(2, 2);
    3. texture.LoadImage(bytes);
    The downside of this approach, it doesn't work on every platform. For example, it won't work on Android.


    A slightly more difficult way to this, would be to use UnityWebRequestTexture:
    https://docs.unity3d.com/ScriptReference/Networking.UnityWebRequestTexture.GetTexture.html

    UnityWebRequestTexture can be used to load local textures as well, I use it to load textures from the "Streaming Assets" folder. It's a little more complicated to implement, but it works an Android too, for example.
    The code must be executed inside a coroutine:
    Code (CSharp):
    1. var www = UnityWebRequestTexture.GetTexture("file://" + filePath);
    2. yield return www.SendWebRequest();
    3. texture = DownloadHandlerTexture.GetContent(www);
     
    Last edited: Mar 22, 2020
  3. Domarius

    Domarius

    Joined:
    Jan 5, 2013
    Posts:
    103
    Thank you for answering my prayers QA Jesus :) Well now I have a few questions:
    • In the example I uploaded, both textures are in the Assets/Resources folder, so shouldn't it work? Why doesn't it?
    • If I actually do want to use the Resources folder for better cross platform support, then what is the correct way to do this, since my example isn't working?
    • Let's say I want to use different approaches for different platforms - allow modding on the desktop platforms by loading textures externally, but use the Resources folder approach for the Switch and Android just in case there are compatability problems with trying to load external resources. Can I use something like "Pre-processor directives" (those compiler IF statements) to have different branching code depending on what platform is being built?
     
    B-Erolskiy likes this.
  4. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,630
    Probably because it's SpriteRenderer and not a regular MeshRenderer:
    https://docs.unity3d.com/Manual/class-SpriteRenderer.html

    I think SpriteRenderer sets its assigned Sprite to the material before rendering, thus it overwrites anything you did assign. Also keep in mind that a Sprite in Unity is more than just a texture. It provides all sort of additional data such as its own vertices for example, which is important once you use SpriteAtlas.

    Unity Technologies recommendation for the Resources API is: Don't use it!
    upload_2020-3-23_7-39-25.png
    https://learn.unity.com/tutorial/assets-resources-and-assetbundles#5c7f8528edbc2a002053b5a7

    Look at Addressables instead:
    https://docs.unity3d.com/Packages/com.unity.addressables@1.1/manual/index.html

    A good tutorial on Addressables is this:

    Addressables can be overwhelming at the beginning, but they take away a lot of implementation details and are supposed to work on every platform. I believe Addressables is a key part of future modding support, but not really sure on it.

    I've no experience creating mod-able games, but from what I've read on the forums and blogs, Unity makes this hard for you. This is worth a new thread or find an existing thread discussing this topic that isn't too old.

    Some console vendor forbid to use the Resources folder on their system. You find more information on this topic in the console vendors Documentation and Guidelines for example.

    Yes. Unity provides preprocessor directives for platforms and various others:
    https://docs.unity3d.com/Manual/PlatformDependentCompilation.html
     
    Last edited: Mar 28, 2020
    Domarius likes this.
  5. Domarius

    Domarius

    Joined:
    Jan 5, 2013
    Posts:
    103
    Thank you, all this info is much appreciated. Seeing how this all works has prompted me to step back and think about how moddable I really want the game to be, and if it is even worth it when the console ports probably won't even support it.
     
    Peter77 likes this.