Skip to content

Instantly share code, notes, and snippets.

@aprius
Created August 14, 2025 05:02
Show Gist options
  • Select an option

  • Save aprius/87bbbbbcf1a820126d48035829ffc069 to your computer and use it in GitHub Desktop.

Select an option

Save aprius/87bbbbbcf1a820126d48035829ffc069 to your computer and use it in GitHub Desktop.
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Linq;
public static class ConvertAssetToPNG
{
// Chỉ hiện menu nếu có ít nhất 1 Texture2D hoặc Sprite được chọn
[MenuItem("Assets/Convert to PNG", true)]
private static bool ValidateConvert()
{
return Selection.objects.Any(o => o is Texture2D || o is Sprite);
}
[MenuItem("Assets/Convert to PNG")]
private static void ConvertSelected()
{
var objs = Selection.objects.Where(o => o is Texture2D || o is Sprite).ToArray();
int success = 0, fail = 0;
foreach (var obj in objs)
{
try
{
if (obj is Sprite s)
ExportSpriteToPng(s);
else if (obj is Texture2D t)
ExportTextureToPng(t, obj.name, AssetDatabase.GetAssetPath(obj));
success++;
}
catch (System.Exception ex)
{
Debug.LogError($"[Convert to PNG] {obj.name}: {ex.Message}");
fail++;
}
}
AssetDatabase.Refresh();
Debug.Log($"[Convert to PNG] Done. Success: {success}, Fail: {fail}");
}
private static void ExportSpriteToPng(Sprite sprite)
{
var tex = sprite.texture;
if (tex == null) throw new System.Exception("Sprite không có texture!");
// Kích thước ảnh xuất đúng theo rect của sprite
int w = Mathf.RoundToInt(sprite.rect.width);
int h = Mathf.RoundToInt(sprite.rect.height);
// Blit full texture vào RT, rồi ReadPixels đúng vùng sprite.rect
RenderTexture rt = RenderTexture.GetTemporary(tex.width, tex.height, 0, RenderTextureFormat.ARGB32);
var prev = RenderTexture.active;
try
{
Graphics.Blit(tex, rt);
RenderTexture.active = rt;
Texture2D readable = new Texture2D(w, h, TextureFormat.RGBA32, false);
// Read vùng con theo rect của sprite (tọa độ pixel)
Rect r = sprite.rect;
readable.ReadPixels(new Rect(r.x, r.y, r.width, r.height), 0, 0, false);
readable.Apply(false, false);
string assetPath = AssetDatabase.GetAssetPath(sprite);
string savePath = BuildSavePath(assetPath, sprite.name);
WritePng(readable, savePath);
}
finally
{
RenderTexture.active = prev;
RenderTexture.ReleaseTemporary(rt);
}
}
private static void ExportTextureToPng(Texture2D tex, string name, string assetPath)
{
int w = tex.width, h = tex.height;
// Blit để “bóc” khỏi GPU format (kể cả compressed) -> RGBA32
RenderTexture rt = RenderTexture.GetTemporary(w, h, 0, RenderTextureFormat.ARGB32);
var prev = RenderTexture.active;
try
{
Graphics.Blit(tex, rt);
RenderTexture.active = rt;
Texture2D readable = new Texture2D(w, h, TextureFormat.RGBA32, false);
readable.ReadPixels(new Rect(0, 0, w, h), 0, 0, false);
readable.Apply(false, false);
string savePath = BuildSavePath(assetPath, name);
WritePng(readable, savePath);
}
finally
{
RenderTexture.active = prev;
RenderTexture.ReleaseTemporary(rt);
}
}
private static string BuildSavePath(string assetPath, string baseName)
{
// Lưu cạnh file gốc
string projectRelativeDir = Path.GetDirectoryName(assetPath) ?? "Assets";
string projectRelative = Path.Combine(projectRelativeDir, baseName + ".png").Replace('\\','/');
// Đổi sang đường dẫn hệ thống
string absolute = Path.Combine(Application.dataPath, projectRelative.Substring("Assets/".Length));
string dir = Path.GetDirectoryName(absolute);
if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
// Tránh trùng tên
string finalPath = absolute;
int i = 1;
while (File.Exists(finalPath))
{
finalPath = Path.Combine(dir, $"{baseName} ({i}).png");
i++;
}
return finalPath;
}
private static void WritePng(Texture2D tex, string absolutePath)
{
byte[] png = tex.EncodeToPNG();
if (png == null || png.Length == 0) throw new System.Exception("EncodeToPNG thất bại.");
File.WriteAllBytes(absolutePath, png);
Debug.Log($"[Convert to PNG] Saved: {absolutePath}");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment