Files
5.24BuYu/Assets/Editor/AtlasPackingFix.cs
T
2026-10-10 05:21:58 +08:00

104 lines
4.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using UnityEditor;
using UnityEngine;
/// <summary>
/// 一键修复图集"渗色 / 串图 / 边缘被邻居图片填充"问题。
///
/// 症状:圆形等带透明边缘的图片,四周被其他图片的像素填充;正方形区域采样/裁剪时会取到邻居图。
/// 成因:padding 过小 + 紧致打包(透明边被裁掉) + 未开 Alpha 扩张 + 图集可能被降采样。
///
/// 本工具对图集的 packingSettings 统一设置:
/// padding 4 → 8 相邻 sprite 之间留出大于压缩块的间隙
/// enableTightPacking off 不再裁掉透明边,sprite 保持完整矩形(正方形区域只含自己)
/// enableRotation off 不在图集内旋转贴图,避免采样方向错乱(串图)
/// enableAlphaDilation on 边缘颜色向外扩张,滤色采样不会取到邻居像素
///
/// 改完必须:重建 Addressables 内容 → 重出包。
/// </summary>
public static class AtlasPackingFix
{
private const int Padding = 8;
private const bool KeepRotation = false; // 需要省图集空间时可改回 true
[MenuItem("Tools/图集工具/修复所有图集(渗色·串图)")]
public static void FixAll()
{
var list = new List<string>();
foreach (var f in Directory.GetFiles("Assets", "*.spriteatlasv2", SearchOption.AllDirectories))
list.Add(f.Replace('\\', '/'));
foreach (var f in Directory.GetFiles("Assets", "*.spriteatlas", SearchOption.AllDirectories))
list.Add(f.Replace('\\', '/'));
if (list.Count == 0) { Debug.LogWarning("[图集修复] 没找到任何图集"); return; }
Apply(list);
}
[MenuItem("Tools/图集工具/修复选中图集(渗色·串图)")]
public static void FixSelected()
{
var list = new List<string>();
foreach (var guid in Selection.assetGUIDs)
{
var p = AssetDatabase.GUIDToAssetPath(guid);
if (p.EndsWith(".spriteatlas") || p.EndsWith(".spriteatlasv2"))
list.Add(p);
}
if (list.Count == 0)
{
Debug.LogWarning("[图集修复] 请先在 Project 里选中至少一个 .spriteatlas / .spriteatlasv2");
return;
}
Apply(list);
}
private static void Apply(List<string> paths)
{
int ok = 0, skip = 0;
try
{
AssetDatabase.StartAssetEditing();
foreach (var path in paths)
{
var importer = AssetImporter.GetAtPath(path);
if (importer == null) { skip++; continue; }
// 用反射拿 packingSettings,避免不同 Unity 版本字段可见性差异导致编译问题
var prop = importer.GetType().GetProperty("packingSettings");
if (prop == null || !prop.CanRead || !prop.CanWrite)
{
Debug.LogWarning($"[图集修复] 跳过(无 packingSettings): {path}");
skip++;
continue;
}
object boxed = prop.GetValue(importer); // 装箱的结构体副本
var st = boxed.GetType();
SetField(st, boxed, "padding", Padding);
SetField(st, boxed, "enableTightPacking", false);
SetField(st, boxed, "enableRotation", KeepRotation);
SetField(st, boxed, "enableAlphaDilation", true);
prop.SetValue(importer, boxed);
importer.SaveAndReimport();
ok++;
Debug.Log($"[图集修复] {Path.GetFileName(path)} → padding={Padding}, TightPacking=off, Rotation={(KeepRotation ? "on" : "off")}, AlphaDilation=on");
}
}
finally
{
AssetDatabase.StopAssetEditing();
AssetDatabase.Refresh();
}
Debug.Log($"[图集修复] 完成:处理 {ok} 个,跳过 {skip} 个。请重建 Addressables 内容后重出包。");
}
private static void SetField(Type t, object boxed, string name, object value)
{
var f = t.GetField(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
if (f != null) f.SetValue(boxed, value);
else Debug.LogWarning($"[图集修复] 字段不存在,已跳过: {name}");
}
}