Skip to content

Instantly share code, notes, and snippets.

@Long18
Last active October 3, 2024 03:11
Show Gist options
  • Save Long18/f10c45f36a1a9189b4b950a87dbc1ea7 to your computer and use it in GitHub Desktop.
Save Long18/f10c45f36a1a9189b4b950a87dbc1ea7 to your computer and use it in GitHub Desktop.
This Unity editor script exports individual sub-sprites from a selected sprite asset as PNG files.
using System.IO;
using UnityEditor;
using UnityEngine;
namespace Long18.Utils
{
/// <summary>
/// Utility class for exporting individual sub-sprites from a selected sprite asset to PNG files.
/// </summary>
public class ExportSubSprites : Editor
{
[MenuItem("Assets/Export Sub-Sprites")]
public static void ExportSelectedSubSprites()
{
string folderPath = EditorUtility.OpenFolderPanel("Export sub-sprites to folder", "", "");
if (string.IsNullOrEmpty(folderPath)) return;
foreach (var selectedObject in Selection.objects)
{
if (selectedObject is Sprite sprite)
{
Texture2D extractedTexture = SpriteExtractor.Extract(sprite);
SpriteSaver.Save(extractedTexture, folderPath);
}
}
SpriteSaver.OpenExportFolder(folderPath);
}
[MenuItem("Assets/Export Sub-Sprites", true)]
private static bool CanExportSelectedSubSprites()
{
return Selection.activeObject is Sprite;
}
}
/// <summary>
/// Provides functionality to extract the texture region of a sprite.
/// </summary>
public static class SpriteExtractor
{
/// <summary>
/// Extracts the texture region occupied by the sprite and returns a new Texture2D.
/// </summary>
/// <param name="sprite">The sprite to extract from.</param>
/// <returns>A new Texture2D containing the extracted sprite region.</returns>
public static Texture2D Extract(Sprite sprite)
{
Texture2D sourceTexture = sprite.texture;
Rect spriteRect = sprite.textureRect;
Texture2D readableTexture = CreateReadableTexture(sourceTexture);
Texture2D croppedTexture = CropTextureToSprite(readableTexture, spriteRect);
croppedTexture.name = $"{sprite.name}";
return croppedTexture;
}
/// <summary>
/// Creates a readable copy of the source texture by rendering it into a temporary RenderTexture.
/// </summary>
private static Texture2D CreateReadableTexture(Texture2D sourceTexture)
{
RenderTexture temporaryRenderTexture =
RenderTexture.GetTemporary(sourceTexture.width, sourceTexture.height, 0);
Graphics.Blit(sourceTexture, temporaryRenderTexture);
RenderTexture previousRenderTexture = RenderTexture.active;
RenderTexture.active = temporaryRenderTexture;
Texture2D readableTexture = new Texture2D(sourceTexture.width, sourceTexture.height);
readableTexture.ReadPixels(new Rect(0, 0, temporaryRenderTexture.width, temporaryRenderTexture.height), 0,
0);
readableTexture.Apply();
RenderTexture.active = previousRenderTexture;
RenderTexture.ReleaseTemporary(temporaryRenderTexture);
return readableTexture;
}
/// <summary>
/// Crops the given readable texture to match the sprite's defined rectangle.
/// </summary>
private static Texture2D CropTextureToSprite(Texture2D readableTexture, Rect spriteRect)
{
Texture2D croppedTexture = new Texture2D((int)spriteRect.width, (int)spriteRect.height);
Color[] spritePixels = readableTexture.GetPixels((int)spriteRect.x, (int)spriteRect.y,
(int)spriteRect.width, (int)spriteRect.height);
croppedTexture.SetPixels(spritePixels);
croppedTexture.Apply();
return croppedTexture;
}
}
/// <summary>
/// Handles saving Texture2D objects to PNG files.
/// </summary>
public static class SpriteSaver
{
/// <summary>
/// Saves a Texture2D as a PNG file to the specified directory.
/// </summary>
/// <param name="texture">The texture to save.</param>
/// <param name="directoryPath">The directory to save the file in.</param>
public static void Save(Texture2D texture, string directoryPath)
{
if (!Directory.Exists(directoryPath))
{
Directory.CreateDirectory(directoryPath);
}
string filePath = Path.Combine(directoryPath, $"{texture.name}.png");
File.WriteAllBytes(filePath, texture.EncodeToPNG());
}
/// <summary>
/// Opens the specified directory in the system's file explorer.
/// </summary>
/// <param name="directoryPath">The directory to open.</param>
public static void OpenExportFolder(string directoryPath)
{
if (Directory.Exists(directoryPath))
{
EditorUtility.RevealInFinder(directoryPath);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment