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

Issues Dynamically Creating Sprites and Saving Them

Discussion in 'Scripting' started by cjddmut, Apr 11, 2015.

  1. cjddmut

    cjddmut

    Joined:
    Nov 19, 2012
    Posts:
    177
    I've created an editor script that will dynamically create sprites and save them to my asset folders. It mostly works correctly except that pixelsPerUnit isn't saving correctly. I determine the appropriate pixelsPerUnit (say in this case it's 30) but when the sprite is saved it always goes with the default of 100.

    While we're at it, I was having issue saving he texture originally so I just use System.IO and refresh the asset database. This has the undesired consequence that my check for not generated mipmaps is ignored (but less of an issue).

    The code for saving the sprite.
    Code (CSharp):
    1.  
    2. void SaveSprite(Texture2D tex)
    3. {
    4.     string assetPath = "Assets/Sprites/ExampleTex.png";
    5.  
    6.     Sprite sp = Sprite.Create(
    7.         tex,
    8.         new Rect(0, 0, tex.width, tex.height),
    9.         new Vector2(0, 0),
    10.         30);
    11.  
    12.     sp.name = "SpriteName";
    13.  
    14.     Debug.Log("Saved PPU: " + sp.pixelsPerUnit); // Saved PPU: 30
    15.  
    16.     // Would prefer a Unity specific way to do this but AssetDatabase.CreateAsset wasn't working.
    17.     // Due to it being a .png instead of .asset?
    18.     File.WriteAllBytes(Application.dataPath + "/../" + assetPath, tex.EncodeToPNG());
    19.     AssetDatabase.Refresh();
    20.     AssetDatabase.AddObjectToAsset(sp, assetPath);
    21.     AssetDatabase.SaveAssets();
    22.  
    23.     sp = AssetDatabase.LoadAssetAtPath(assetPath, typeof (Sprite)) as Sprite;
    24.  
    25.     Debug.Log("Loaded PPU: " + s.pixelsPerUnit); // Loaded PPU: 100
    26. }
    27.  
    Thanks in advance!
    C.J.
     
  2. Miguel-Ferreira

    Miguel-Ferreira

    Joined:
    May 8, 2015
    Posts:
    90
    I know it's been a long time, but I had this same problem today.

    Ended up using this to correctly save a sprite keeping its pixelsPerUnit.

    Code (CSharp):
    1. Sprite SaveSpriteToEditorPath(Sprite sp,string path) {
    2.  
    3.         string dir = Path.GetDirectoryName (path);
    4.  
    5.         Directory.CreateDirectory (dir);
    6.  
    7.         File.WriteAllBytes(path, sp.texture.EncodeToPNG());
    8.         AssetDatabase.Refresh();
    9.         AssetDatabase.AddObjectToAsset(sp, path);
    10.         AssetDatabase.SaveAssets();
    11.  
    12.         TextureImporter ti = AssetImporter.GetAtPath (path) as TextureImporter;
    13.  
    14.         ti.spritePixelsPerUnit = sp.pixelsPerUnit;
    15.         ti.mipmapEnabled = false;
    16.         EditorUtility.SetDirty (ti);
    17.         ti.SaveAndReimport ();
    18.  
    19.         return  AssetDatabase.LoadAssetAtPath(path, typeof (Sprite)) as Sprite;
    20.     }
     
  3. kala476

    kala476

    Joined:
    Feb 28, 2018
    Posts:
    1
    I just tried this and I am getting "Unnknown error occured while loading :(
    I get the texture encoded created correctly then the rest does not happen
     
  4. idbrii

    idbrii

    Joined:
    Aug 18, 2014
    Posts:
    51
    I think AssetDatabase.AddObjectToAsset is supposed to copy the Sprite properties to the created asset, but it's the source of the "Unnknown error". Maybe it broke since Miguel-Ferreira's post. Since that doesn't work, I also needed to set the texture to use the Sprite type so it can be loaded as a Sprite:

    ti.textureType = TextureImporterType.Sprite;

    (Just like after dragging a png into the project.)


    My function in Unity 2019.4.7 looks like this:

    Code (CSharp):
    1. // proj_path should be relative to the Assets folder.
    2. static Sprite SaveSpriteAsAsset(Sprite sprite, string proj_path)
    3. {
    4.     var abs_path = Path.Combine(Application.dataPath, proj_path);
    5.     proj_path = Path.Combine("Assets", proj_path);
    6.  
    7.     Directory.CreateDirectory(Path.GetDirectoryName(abs_path));
    8.     File.WriteAllBytes(abs_path, ImageConversion.EncodeToPNG(sprite.texture));
    9.  
    10.     AssetDatabase.Refresh();
    11.  
    12.     var ti = AssetImporter.GetAtPath(proj_path) as TextureImporter;
    13.     ti.spritePixelsPerUnit = sprite.pixelsPerUnit;
    14.     ti.mipmapEnabled = false;
    15.     ti.textureType = TextureImporterType.Sprite;
    16.  
    17.     EditorUtility.SetDirty(ti);
    18.     ti.SaveAndReimport();
    19.  
    20.     return AssetDatabase.LoadAssetAtPath<Sprite>(proj_path);
    21. }
     
    Last edited: Apr 29, 2021