Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Renaming Sprite Slices in Script

Discussion in 'Immediate Mode GUI (IMGUI)' started by edwardrowe, Aug 3, 2015.

  1. edwardrowe

    edwardrowe

    Joined:
    Feb 11, 2014
    Posts:
    52
    I'm working on a pixel art game that uses a lot of sliced sprite sheets, and I'm trying to tool up in order to minimize how often animation clips and other references to sprites break when using the autoslicing feature.

    I'm starting simple, trying to do a tool to rename a sprite sheet and its slices without breaking all references to the sprites. But even this seems difficult. I have the slices renaming, but SpriteRenderers and animations that reference the old slices break (Missing Sprite).

    I'm currently marking my importer settings dirty, modifying the SpriteMetaData, and reimporting using TextureImporter.SaveAndReimport (). I've also tried using AssetDatabase.ImportAsset (path, ImportAssetOptions.ForcedUpdate), and every combination thereof but any method that saves the file seems to break the references.

    I've noticed that the fileIDToRecycleName in the meta file is different when I manually rename the sprites versus through script. If I use the script I get additional fileIDs, but if I rename it manually it changes the names associated with each fileID.

    Can anyone explain how I can modify the SpriteMetaData without breaking references? I'm also curious what the difference is between the two reimporting methods above. Many people do both SaveAndReimport and ForcedUpdate, but that seems unnecessary, based on the documentation.

    Thanks!

    You can find the code in my Answers post here: http://answers.unity3d.com/questions/1015984/how-to-rename-sprite-slices-in-script-without-brea.html

    *Edit* fixed spelling mistakes
     
    Last edited: Aug 3, 2015
  2. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
  3. edwardrowe

    edwardrowe

    Joined:
    Feb 11, 2014
    Posts:
    52
    Thanks for the reply!

    After your suggestion I looked into using RenameAsset to rename the Sprites, but it seems like it won't work for sprites since they are all at the same path (which is the path of the Texture they are "parented" to). If I do RenameAsset on their path, it will just rename the root Texture, which I don't want (yet).
     
  4. edwardrowe

    edwardrowe

    Joined:
    Feb 11, 2014
    Posts:
    52
    I've been digging some more and think the fileIDToRecycleName is basically like a GUID for the sprite, and the issue is related to the extra IDs instead of renaming the existing names. The extra IDs are probably added when I assign the new spritesheet to the importer (line 36). It probably compares the new sprite names against the RecycleNames and if it doesn't find it it creates a new ID. I'm thinking it's basically a Unity bug since there's no way to force it to also rename the RecycleName that I can find.

    A workaround (that might have issues - I have no idea) is to edit the .meta file manually (assuming you have it forced to text). You can replace each sprite name with whatever you want, and it seems to keep references in the editor in tact. Just be sure to edit both the fileIDToRecycleName (if there is any) and the SpriteMetaData.
     
  5. edwardrowe

    edwardrowe

    Joined:
    Feb 11, 2014
    Posts:
    52
  6. Deni35

    Deni35

    Joined:
    Jul 10, 2012
    Posts:
    43
    There is internal class PatchImportSettingRecycleID, PatchMultiple(SerializedObject serializedObject, int classID, string[] oldNames, string[] newNames) method.

    Based on that method I wrote my methods for replacing old names to new names.

    Code (csharp):
    1.  
    2.             var oldSprites = importer.spritesheet;
    3.             var newSprites = sprites.Where( spr => spr.texture ).Select( CreateSpriteMetaData ).ToArray();
    4.             importer.spritesheet = newSprites;
    5.             SpriteRenamingHelper.Rename( importer, oldSprites, newSprites );
    6. ...
    7.  
    8.  
    9.  
    10.        
    11.         public static void Rename(TextureImporter importer, SpriteMetaData[] oldSprites, SpriteMetaData[] newSprites) {
    12.             var oldNames = oldSprites.Select( spr => spr.name ).ToArray();
    13.             var newNames = newSprites.Select( spr => spr.name ).ToArray();
    14.             var renames = FindRenames( oldNames, newNames );
    15.             ApplyRenames( importer, renames );
    16.         }
    17.  
    18.  
    19.         private static Dictionary<string, string> FindRenames(string[] oldNames, string[] newNames) {
    20.             Dictionary<string, string> renames = new Dictionary<string, string>(); // key: oldName, value: newName
    21.  
    22.             foreach (string oldName in oldNames) {
    23.                 if (!newNames.Contains( oldName )) {
    24.                     string newName = LevenshteinDistance.FindNewName( oldName, newNames );
    25.                     if (newName != null) renames.Add( oldName, newName );
    26.                 }
    27.             }
    28.  
    29.             return renames;
    30.         }
    31.  
    32.  
    33.         private static void ApplyRenames(TextureImporter importer, Dictionary<string, string> renames) {
    34.             var obj = new SerializedObject( importer );
    35.             var fileIDToRecycleName = obj.FindProperty( "m_FileIDToRecycleName" );
    36.  
    37.             foreach (SerializedProperty pairProp in fileIDToRecycleName) {
    38.                 //SerializedProperty idProp = pairProp.FindPropertyRelative( "first" );
    39.                 SerializedProperty nameProp = pairProp.FindPropertyRelative( "second" );
    40.  
    41.                 if (renames.ContainsKey( nameProp.stringValue )) {
    42.                     nameProp.stringValue = renames[nameProp.stringValue];
    43.                 }
    44.             }
    45.  
    46.             obj.ApplyModifiedPropertiesWithoutUndo();
    47.             obj.Dispose();
    48.         }
    49.  
     
    Last edited: Apr 21, 2017
  7. edwardrowe

    edwardrowe

    Joined:
    Feb 11, 2014
    Posts:
    52
    reinfeldx likes this.