How to Rename Sprite Slices in Script Without Breaking References

I’ve been trying to write a quick script to rename sprite slices without breaking references to the sprites in sprite renderers or animations. I thought it would be simple since you can do this manually through the Sprite Editor without any issues, but I have run into a difficult snag.

The script I currently have seems to work fine, except that my references break (“Missing Sprite”).

I’ve tried using different methods for importing the asset, as I find that pretty unclear from the Unity documentation. I’ve used both AssetImporter.SaveAndReimport (), and AssetDatabase.ReimportAsset (path, ImportAssetOptions.ForceUpdate), (both seeming to require calling EditorUtility.SetDirty() on my import settings), but both have the same results.

In examining the meta files before and after my script, I see the renamed file has a few references to the old files in the “fileIDToRecycleName” section, and I’m wondering if that might be the issue. For example:

Original file:

fileIDToRecycleName:

21300000: UI_Buttons_0
21300002: UI_Buttons_1
21300004: UI_Buttons_2
21300006: UI_Buttons_3

Renamed File:

fileIDToRecycleName:

21300000: UI_Buttons_0
21300002: UI_Buttons_1
21300004: UI_Buttons_2
21300006: UI_Buttons_3
21300008: RenamedSprite_0
21300010: RenamedSprite_1
21300012: RenamedSprite_2
21300014: RenamedSprite_3

If I rename the slices manually they will keep the original fileID.

Has anyone solved this issue? Can anyone tell me how to rewrite Texture Import Settings on slices without regenerating their meta data?


Code:

using UnityEngine;
using UnityEditor;

public class SpritesheetRename : MonoBehaviour
{
	[MenuItem ("Assets/Rename Spritesheet")]
	public static void RenameSpritesheet ()
	{
		RenameSelectedTexture ();
	}

	static void RenameSelectedTexture ()
	{
		// Validation
		var selectedObject = Selection.activeObject;
		if (!AssetDatabase.Contains (selectedObject)) {
			Debug.LogError ("Selected object not found in Asset Database.");
			return;
		}
		
		string path = AssetDatabase.GetAssetPath (selectedObject);
		var importer = AssetImporter.GetAtPath (path) as TextureImporter;
		if (importer == null) {
			Debug.LogError ("Selected object not found in Asset Database.");
			return;
		}

		// Rename the slices
		SpriteMetaData[] spritesheet = importer.spritesheet;
		bool textureHasSpritesheet = spritesheet != null && spritesheet.Length > 0;
		if (textureHasSpritesheet)
		{
			for (int i = 0; i < spritesheet.Length; i++) {
				spritesheet*.name = "RenamedSprite_" + i;*
  •  	}*
    
  •  	importer.spritesheet = spritesheet;*
    
  •  	// Reimport the asset*
    
  •  	EditorUtility.SetDirty (importer); // Flag dirty for SaveAndReimport to find it*
    
  •  	importer.SaveAndReimport ();*
    
  •  	// Don't need to do this since settings were already reimported via SaveAndReimport*
    
  •  	//AssetDatabase.ImportAsset (path, ImportAssetOptions.ForceUpdate);* 
    
  •  }*
    
  •  // TODO: Rename the asset as well once slice renaming is working*
    
  •  //AssetDatabase.RenameAsset (path, "Renamed.png");*
    
  •  //AssetDatabase.Refresh ();*
    
  • }*

  • [MenuItem (“Assets/Rename Spritesheet”, true)]*

  • public static bool IsValidTargetForPalette ()*

  • {*

  •  if (Selection.activeObject == null) {*
    
  •  	return false;*
    
  •  }*
    
  •  if (Selection.objects.Length > 1) {*
    
  •  	return false;*
    
  •  }*
    
  •  return Selection.activeObject.GetType () == typeof(Texture2D);*
    
  • }*
    }
    I’ve based my script off of similar questions I’ve found here:
    - Editor script to slice sprites - Questions & Answers - Unity Discussions
    - http://answers.unity3d.com/questions/753664/

I created a workaround script for this, after discussions with @artwen

This script renames the texture and its auto-sliced sprites while maintaining references by modifying the .meta data file. Use it at your own risk =)

Hello @edwardrowe , I have been going through both scripts you made. It seems this script would sort of be what I am looking for (I am looking for a script that has a tab on the main menu, that uses a list format such as spriteslice1=renamed1, spriteslice2=renamed2 etc.) Your second working script uses prefixes, and seems to only change the spritesheet name itself. I am going to try to blend together a bunch of scripts until I have what I am looking for, but I am quite new to C# and wondering if you have any insight on the topic.

Thanks,

using UnityEngine;
using UnityEditor;

public class RenameSpritesheet : EditorWindow
{
	static string[] names = new string[20];
	static TextureImporter selectedTextureImporter
	{
		get
		{
			var selectedObject = Selection.activeObject;
			if (!AssetDatabase.Contains(selectedObject))
			{
				Debug.LogError("Selected object not found in Asset Database.");
				return null;
			}
			return (TextureImporter)AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(selectedObject));
		}
	}

	[MenuItem("Assets/Rename Spritesheet")]
	public static void ShowRenameSpritesheetWindow()
	{
		EditorWindow.GetWindow<RenameSpritesheet>(true, "Rename Texture", true);
	}

	[MenuItem("Assets/Rename Spritesheet", true)]
	public static bool IsSelectionSprite()
	{
		if (Selection.activeObject == null)
		{
			return false;
		}

		if (Selection.objects.Length > 1)
		{
			return false;
		}

		return Selection.activeObject.GetType() == typeof(Texture2D);
	}

	void OnGUI()
	{
		EditorGUILayout.HelpBox("This SpritesheetRename tool is used to rename a texture that's been autosliced. It replaces " +
			"all instances of the old prefix with a new one, and renames the Texture to match.", MessageType.None);

        for (int i = 0; i < selectedTextureImporter.spritesheet.Length; i++)
        {
            SpriteMetaData s = selectedTextureImporter.spritesheet*;*

names = EditorGUILayout.TextField(s.name, names*);*
* }*

* if (GUILayout.Button(“Rename”))*
* {*
SpriteMetaData[] sprites = selectedTextureImporter.spritesheet;
* for (int i = 0; i < selectedTextureImporter.spritesheet.Length; i++)*
* {*
sprites_.name = names*;
}
selectedTextureImporter.spritesheet = sprites;
EditorUtility.SetDirty(selectedTextureImporter);
selectedTextureImporter.SaveAndReimport();*_

* // Reimport/refresh asset.*
* AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(selectedTextureImporter), ImportAssetOptions.ForceUpdate);*
* Close();*
* }*
* }*
}