}

유니티 Sprite를 한 번에 Slice하자!

유니티 작업을 하다 보면, png을 받아서 Sprtie로 사용하는 경우가 빈번합니다.

png 파일들

위 png파일들의 경우 기본은 Default이며, UI Image같은데에 사용하려면  Default -> Sprite로 Type을 변경해주어야 합니다.

하지만...!! 거기서 끝이 아니죠.

 

Slice 작업

Open Sprite Editor를 눌러서 우측 사진처럼 Slicing을 해주어야 

Sprite

위 사진 처럼 Sprite로 사용할 수 있게 됩니다.

 

한 장이면 상관 없지만, 여러장일 경우 이런 노가다를 하기엔 너무 힘들어서 Editor를 이용하여 딸-칵 해결할 수 있습니다.

저의 경우에는 항상 대부분 Sprite를 한 장으로 Slicing하기에 아래 코드는 "한 장"으로만 슬라이싱 됩니다.

 

2d game의 경우 여러장으로 Slice를 많이 하던데 전 2d game은 안만들기 때문에 ㅎㅎ..

 

아무튼 아래 코드를 사용하시면 됩니다.

#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;

public class AutoSpriteSlicerWindow : EditorWindow
{
    private readonly List<string> dropPaths = new List<string>();
    private Vector2 scroll;

    [MenuItem("Tools/Auto Sprite Slicer (Single)")]
    private static void Open()
    {
        var win = GetWindow<AutoSpriteSlicerWindow>(true, "Auto Sprite Slicer");
        win.minSize = new Vector2(420, 360);
    }

    private void OnGUI()
    {
        EditorGUILayout.LabelField("Single Full-Image Sprite", EditorStyles.boldLabel);

        var dropRect = GUILayoutUtility.GetRect(0, 64, GUILayout.ExpandWidth(true));
        GUI.Box(dropRect, "여기에 PNG(또는 폴더)를 드래그\n현재: " + dropPaths.Count + "개", EditorStyles.helpBox);
        HandleDragAndDrop(dropRect);

        using (new EditorGUILayout.HorizontalScope())
        {
            if (GUILayout.Button("Add Selected PNGs/Folders")) AddPathsFromObjects(Selection.objects, true);
            if (GUILayout.Button("Clear List")) dropPaths.Clear();
        }

        using (new EditorGUILayout.VerticalScope("box"))
        {
            EditorGUILayout.LabelField("대상 목록", EditorStyles.boldLabel);
            scroll = EditorGUILayout.BeginScrollView(scroll, GUILayout.MaxHeight(180));
            for (int i = 0; i < dropPaths.Count; i++)
            {
                using (new EditorGUILayout.HorizontalScope())
                {
                    EditorGUILayout.LabelField(dropPaths[i], GUILayout.ExpandWidth(true));
                    if (GUILayout.Button("X", GUILayout.Width(28))) { dropPaths.RemoveAt(i); i--; }
                }
            }
            EditorGUILayout.EndScrollView();

            using (new EditorGUILayout.HorizontalScope())
            {
                GUILayout.FlexibleSpace();
                EditorGUI.BeginDisabledGroup(dropPaths.Count == 0);
                if (GUILayout.Button("Convert to Single Sprite (" + dropPaths.Count + ")", GUILayout.Height(28)))
                {
                    ConvertToSingleSprite();
                }
                EditorGUI.EndDisabledGroup();
            }
        }

        EditorGUILayout.HelpBox("버튼 한 번으로 각 PNG를 전체 한 장짜리 Sprite(단일)로 만듭니다.", MessageType.Info);
    }

    private void HandleDragAndDrop(Rect r)
    {
        var e = Event.current;
        if (!r.Contains(e.mousePosition)) return;
        if (e.type == EventType.DragUpdated || e.type == EventType.DragPerform)
        {
            DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
            if (e.type == EventType.DragPerform)
            {
                DragAndDrop.AcceptDrag();
                AddPathsFromObjects(DragAndDrop.objectReferences, true);
            }
            e.Use();
        }
    }

    private void AddPathsFromObjects(UnityEngine.Object[] objs, bool includeFolders)
    {
        var newPaths = new List<string>();
        foreach (var obj in objs)
        {
            if (obj == null) continue;
            var path = AssetDatabase.GetAssetPath(obj);
            if (string.IsNullOrEmpty(path)) continue;

            if (includeFolders && Directory.Exists(path))
            {
                var guids = AssetDatabase.FindAssets("t:Texture2D", new[] { path });
                foreach (var guid in guids)
                {
                    var p = AssetDatabase.GUIDToAssetPath(guid);
                    if (p.EndsWith(".png", StringComparison.OrdinalIgnoreCase)) newPaths.Add(p);
                }
            }
            else
            {
                if (path.EndsWith(".png", StringComparison.OrdinalIgnoreCase)) newPaths.Add(path);
            }
        }
        foreach (var p in newPaths) if (!dropPaths.Contains(p)) dropPaths.Add(p);
    }

    private void ConvertToSingleSprite()
    {
        int processed = 0;
        try
        {
            AssetDatabase.StartAssetEditing();
            foreach (var path in dropPaths)
            {
                var importer = AssetImporter.GetAtPath(path) as TextureImporter;
                if (importer == null) continue;
                if (!path.EndsWith(".png", StringComparison.OrdinalIgnoreCase)) continue;

                importer.textureType = TextureImporterType.Sprite;
                importer.spriteImportMode = SpriteImportMode.Single; 
                importer.alphaIsTransparency = true;
                importer.spritePixelsPerUnit = 100f; 
                importer.spritePivot = new Vector2(0.5f, 0.5f); 
                importer.spritesheet = null;
                importer.SaveAndReimport();
                processed++;
            }
        }
        catch (Exception ex)
        {
            Debug.LogError(ex);
        }
        finally
        {
            AssetDatabase.StopAssetEditing();
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
        }
        Debug.Log("[AutoSpriteSlicer] Single Sprite 완료: " + processed + "/" + dropPaths.Count);
    }
}
#endif

 

Auto Sprite

Image들이 존재하는 폴더를 드래그 & 드롭해서 넣어주신 후, Convert 버튼만 눌러주면 모든 Image들이 한 번에 Slicing됩니다!

 

다들 편하게 작업하시길!