#if UNITY_IOS using UnityEditor; using UnityEditor.Callbacks; using System.IO; using System.Text; /// /// iOS 出包后自动替换高清 App 图标,解决 Unity 压缩导致图标模糊的问题。 /// 使用方式:将精确尺寸的 PNG 图标放入 Assets/Icons/iOS/ 目录下,打包时自动生效。 /// 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