using UnityEngine; using UnityEngine.UI; using SFB; using System.Collections.Generic; using System.IO; using System.Text.RegularExpressions; public class MultiGroupSpriteMerger : MonoBehaviour { public Button selectFolderButton; public Text statusText; void Start() { selectFolderButton.onClick.AddListener(OnSelectFolder); } void OnSelectFolder() { var paths = StandaloneFileBrowser.OpenFolderPanel("选择包含序列帧图片的文件夹", "", false); if (paths.Length > 0) { ProcessAllGroups(paths[0]); } } void ProcessAllGroups(string folderPath) { statusText.text = "开始读取图片..."; string[] files = Directory.GetFiles(folderPath, "*.png"); Dictionary>> groupMap = new(); Regex regex = new Regex(@"(\d+)_(\d+)\.png"); foreach (var path in files) { string fileName = Path.GetFileName(path); Match match = regex.Match(fileName); if (!match.Success) continue; int x = int.Parse(match.Groups[1].Value); int groupIndex = (x - 1) / 8 + 1; int direction = (x - 1) % 8 + 1; Texture2D tex = new Texture2D(2, 2); if (!tex.LoadImage(File.ReadAllBytes(path))) { Debug.LogWarning($"加载图片失败: {fileName}"); continue; } tex.name = fileName; if (!groupMap.ContainsKey(groupIndex)) groupMap[groupIndex] = new Dictionary>(); if (!groupMap[groupIndex].ContainsKey(direction)) groupMap[groupIndex][direction] = new List(); groupMap[groupIndex][direction].Add(tex); } int exportedCount = 0; foreach (var group in groupMap) { int groupId = group.Key; var directions = group.Value; List rowHeights = new(); List> rows = new(); List rowWidths = new(); foreach (var dir in directions) { var frames = dir.Value; int maxH = 0, totalW = 0; // 排序帧 frames.Sort((a, b) => { var ma = Regex.Match(a.name, @"\d+_(\d+)"); var mb = Regex.Match(b.name, @"\d+_(\d+)"); return int.Parse(ma.Groups[1].Value).CompareTo(int.Parse(mb.Groups[1].Value)); }); foreach (var tex in frames) { totalW += tex.width; maxH = Mathf.Max(maxH, tex.height); } rowWidths.Add(totalW); rowHeights.Add(maxH); rows.Add(frames); } int totalHeight = 0; foreach (int h in rowHeights) totalHeight += h; int totalWidth = 0; foreach (int w in rowWidths) totalWidth = Mathf.Max(totalWidth, w); Texture2D result = new Texture2D(totalWidth, totalHeight, TextureFormat.RGBA32, false); Color[] clear = new Color[totalWidth * totalHeight]; for (int i = 0; i < clear.Length; i++) clear[i] = new Color(0, 0, 0, 0); result.SetPixels(clear); int yOffset = totalHeight; for (int row = 0; row < rows.Count; row++) { List frames = rows[row]; int xOffset = 0; int rowHeight = rowHeights[row]; yOffset -= rowHeight; foreach (var tex in frames) { try { Color[] pixels = tex.GetPixels(); if (pixels.Length != tex.width * tex.height) { Debug.LogWarning($"跳过尺寸异常图像: {tex.name}"); continue; } result.SetPixels(xOffset, yOffset + (rowHeight - tex.height), tex.width, tex.height, pixels); xOffset += tex.width; } catch (System.Exception ex) { Debug.LogError($"绘图出错: {tex.name} - {ex.Message}"); } } } result.Apply(); string savePath = Path.Combine(folderPath, $"combined_group_{groupId}.png"); File.WriteAllBytes(savePath, result.EncodeToPNG()); Debug.Log($"导出完成:{savePath}"); exportedCount++; } statusText.text = $"完成,共导出 {exportedCount} 张大图"; } }