killapp/Assets/Editor/iOSIconPostProcessor.cs
yuqucheng 5e0560d75a feat(editor): add iOS icon auto-replace post processor
解决Unity打包iOS时压缩图标导致模糊的问题,将Assets/Icons/iOS/下的高清图标自动替换到Xcode项目的Assets.car中
2026-07-07 10:43:07 +08:00

101 lines
3.7 KiB
C#

#if UNITY_IOS
using UnityEditor;
using UnityEditor.Callbacks;
using System.IO;
using System.Text;
/// <summary>
/// iOS 出包后自动替换高清 App 图标,解决 Unity 压缩导致图标模糊的问题。
/// 使用方式:将精确尺寸的 PNG 图标放入 Assets/Icons/iOS/ 目录下,打包时自动生效。
/// </summary>
public class iOSIconPostProcessor
{
private const string SOURCE_ICON_DIR = "Assets/Icons/iOS/";
// 各尺寸图标配置 (idiom, scale, size, 文件名)
private static readonly (string idiom, string scale, string size, string file)[] ICON_CONFIGS =
{
("iphone", "2x", "20x20", "icon-20@2x.png"),
("iphone", "3x", "20x20", "icon-20@3x.png"),
("iphone", "2x", "29x29", "icon-29@2x.png"),
("iphone", "3x", "29x29", "icon-29@3x.png"),
("iphone", "2x", "40x40", "icon-40@2x.png"),
("iphone", "3x", "40x40", "icon-40@3x.png"),
("iphone", "2x", "60x60", "icon-60@2x.png"),
("iphone", "3x", "60x60", "icon-60@3x.png"),
("ipad", "2x", "20x20", "icon-20@2x.png"),
("ipad", "2x", "29x29", "icon-29@2x.png"),
("ipad", "2x", "40x40", "icon-40@2x.png"),
("ipad", "2x", "76x76", "icon-76@2x.png"),
("ipad", "2x", "83.5x83.5", "icon-83.5@2x.png"),
("ios-marketing", "1x", "1024x1024", "icon-1024.png"),
};
[PostProcessBuild(int.MaxValue)]
public static void OnPostProcessBuild(BuildTarget target, string pathToBuiltProject)
{
if (target != BuildTarget.iOS) return;
string iconSetPath = Path.Combine(pathToBuiltProject, "Unity-iPhone/Images.xcassets/AppIcon.appiconset");
if (!Directory.Exists(iconSetPath))
{
UnityEngine.Debug.LogWarning($"[iOSIconPostProcessor] 未找到 AppIcon.appiconset 目录: {iconSetPath}");
return;
}
int copied = 0;
foreach (var cfg in ICON_CONFIGS)
{
string src = Path.GetFullPath(Path.Combine(SOURCE_ICON_DIR, cfg.file));
string dst = Path.Combine(iconSetPath, cfg.file);
if (File.Exists(src))
{
File.Copy(src, dst, overwrite: true);
copied++;
}
else
{
UnityEngine.Debug.LogWarning($"[iOSIconPostProcessor] 缺少图标文件: {src}");
}
}
if (copied > 0)
{
WriteContentsJson(iconSetPath);
UnityEngine.Debug.Log($"[iOSIconPostProcessor] 已替换 {copied} 个 App 图标到 Xcode 项目");
}
}
private static void WriteContentsJson(string iconSetPath)
{
var sb = new StringBuilder();
sb.AppendLine("{");
sb.AppendLine(" \"images\" : [");
for (int i = 0; i < ICON_CONFIGS.Length; i++)
{
var cfg = ICON_CONFIGS[i];
sb.Append(" {");
sb.Append($"\"idiom\" : \"{cfg.idiom}\", ");
sb.Append($"\"scale\" : \"{cfg.scale}\", ");
sb.Append($"\"size\" : \"{cfg.size}\"");
if (!string.IsNullOrEmpty(cfg.file))
sb.Append($", \"filename\" : \"{cfg.file}\"");
sb.Append("}");
if (i < ICON_CONFIGS.Length - 1) sb.Append(",");
sb.AppendLine();
}
sb.AppendLine(" ],");
sb.AppendLine(" \"info\" : {");
sb.AppendLine(" \"version\" : 1,");
sb.AppendLine(" \"author\" : \"xcode\"");
sb.AppendLine(" }");
sb.AppendLine("}");
string jsonPath = Path.Combine(iconSetPath, "Contents.json");
File.WriteAllText(jsonPath, sb.ToString());
}
}
#endif