Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

Easy way to make Texture isReadable true by script

Discussion in 'Scripting' started by Henry_Sun, Jul 16, 2021.

  1. Henry_Sun

    Henry_Sun

    Joined:
    Jun 1, 2019
    Posts:
    23
    I found there're a lot workarounds to read a unreadable texture. Like reading raw data or using RenderTexture.
    And I hava a direct way to make the isReadable true.
    Just go to the local texture meta file and change the 0 to 1.
    The drawback is if you don't "AssetDatabase.Refresh();" it, the unity would not response immediately after you did the change.
    However AssetDatabase is under the UnityEditor namespace. So you [Edit: can't] use this at runtime.

    Code (CSharp):
    1.  
    2. using System.IO;
    3. void SetTextureReadable(string AbsoluteFilePath)
    4.     {
    5.         string metadataPath = AbsoluteFilePath + ".meta";
    6.         if (File.Exists(metadataPath))
    7.         {
    8.             List<string> newfile = new List<string>();
    9.  
    10.             string[] lines = File.ReadAllLines(metadataPath);
    11.             foreach (string line in lines)
    12.             {
    13.                 string newline = line;
    14.                 if (newline.Contains("isReadable: 0"))
    15.                 {
    16.                     newline = newline.Replace("isReadable: 0", "isReadable: 1");
    17.                 }
    18.                 newfile.Add(newline);
    19.             }
    20.  
    21.             File.WriteAllLines(metadataPath, newfile.ToArray());
    22.             AssetDatabase.Refresh();
    23.  
    24.         }
    25.     }
     
    Last edited: Jul 16, 2021
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,780
    More specifically you actually CANNOT use this at runtime: try it for yourself, it won't compile!

    Fortunately, there's an easy workaround to get a read-write enabled texture at runtime:

    https://answers.unity.com/questions/988174/create-modify-texture2d-to-readwrite-enabled-at-ru.html

    And I use it in my Jetpack Kurt game to procedurally tint the ground textures on certain levels.

    In case the above link fails, here's the code:

    Code (csharp):
    1. Texture2D duplicateTexture(Texture2D source)
    2. {
    3.     RenderTexture renderTex = RenderTexture.GetTemporary(
    4.                 source.width,
    5.                 source.height,
    6.                 0,
    7.                 RenderTextureFormat.Default,
    8.                 RenderTextureReadWrite.Linear);
    9.  
    10.     Graphics.Blit(source, renderTex);
    11.     RenderTexture previous = RenderTexture.active;
    12.     RenderTexture.active = renderTex;
    13.     Texture2D readableText = new Texture2D(source.width, source.height);
    14.     readableText.ReadPixels(new Rect(0, 0, renderTex.width, renderTex.height), 0, 0);
    15.     readableText.Apply();
    16.     RenderTexture.active = previous;
    17.     RenderTexture.ReleaseTemporary(renderTex);
    18.     return readableText;
    19. }
     
    AndreasClifftop likes this.
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,780
    Whoa... I wouldn't go doing text search/replace on a YAML file either unless there was no other way... that's ... perilous in many ways. What happens when Unity stops using YAML? Or they change 0 to be "false" or something else?

    Did you know you can implement your own custom texture importer?

    https://docs.unity3d.com/ScriptReference/TextureImporter.html

    One of the available fields is ... wait for it!

    https://docs.unity3d.com/ScriptReference/TextureImporter-isReadable.html

    :)
     
  4. Henry_Sun

    Henry_Sun

    Joined:
    Jun 1, 2019
    Posts:
    23
    Thanks for all the information. I'll keep that in mind.
    I've already seen those threads so I mentioned them in my first sentence.
    The upsetting thing is I failed to find the way to implement my custom importer since I've already visited the API page but it doesn't give any examples.
    And I thought that "save and reimport a texture just to change a boolean" is not quite elegant.

    I am writing an editor script so I'm ok with my method as We work at a relatively stable editor version.
     
    Last edited: Jul 16, 2021
  5. adamgolden

    adamgolden

    Joined:
    Jun 17, 2019
    Posts:
    1,498
    If anyone needs to set it by editor script, this works:
    Code (CSharp):
    1. TextureImporter ti = (TextureImporter)AssetImporter.GetAtPath(path);
    2. if (!ti.isReadable)
    3. {
    4.   ti.isReadable = true;
    5.   ti.SaveAndReimport();
    6. }
     
  6. _geo__

    _geo__

    Joined:
    Feb 26, 2014
    Posts:
    1,115
    Here is it wrapped so you can easily read pixel colors from a texture in Editor no matter if readable or not.

    Code (CSharp):
    1. static Color[] getPixels(Texture2D originalTexture, int minX, int minY, int width, int height)
    2. {
    3.     // Get pixel data
    4.     bool isReadable = originalTexture.isReadable;
    5.     TextureImporter ti = null;
    6.     try
    7.     {
    8.         // Ensure original texture is readable
    9.         if (!isReadable)
    10.         {
    11.             var origTexPath = AssetDatabase.GetAssetPath(originalTexture);
    12.             ti = (TextureImporter)AssetImporter.GetAtPath(origTexPath);
    13.             ti.isReadable = true;
    14.             ti.SaveAndReimport();
    15.         }
    16.  
    17.         Color[] pixelData = originalTexture.GetPixels(minX, minY, width, height);
    18.         return pixelData;
    19.     }
    20.     finally
    21.     {
    22.         // Revert
    23.         if (!isReadable && ti != null)
    24.         {
    25.             ti.isReadable = false;
    26.             ti.SaveAndReimport();
    27.         }
    28.     }
    29. }
     
    Last edited: Jan 20, 2023
    Bunny83 likes this.