Platform
iOS App Icon
Unity can only produce an iOS app icon from flat images — the AppIcon.appiconset it writes into the
generated Xcode project. Since iOS 26 the platform prefers an Icon Composer document (a .icon
package) instead: one layered source from which actool renders every appearance (light, dark, tinted,
clear) and every legacy size. Unity has no notion of that format, so the app installs it in a post-build
step.
Using it
-
Build the icon in Icon Composer (ships with Xcode 26) and save it as
<Name>.icon. -
Save it as
Assets/UI/Icons/appIcon/ios/composer~/AppIcon.icon, next to the flat icons. That exact path and name is what the post-process step installs — it looks nowhere else. Unity skips folders whose name ends with~, so the package’s internal images are not imported as project assets and no.metafiles are generated inside it. -
Build for iOS. Nothing else is needed; the icon is picked up automatically.
The name is what ties it to the build: ASSETCATALOG_COMPILER_APPICON_NAME is set to AppIcon, and
Unity’s own AppIcon.appiconset is deleted from Images.xcassets, because actool refuses two app
icons sharing a name in one compilation. Renaming the document means changing the constants in the
post-processor as well.
When no .icon is present the step does nothing and Unity’s generated icons are used, which is still
the case for Android and Web. The PlayerSettings icons therefore remain the source of truth for those
platforms and should be kept in sync with the Icon Composer document by hand.
Keeping the artwork unchanged
Icon Composer applies Liquid Glass effects to every group, which visibly washes out flat artwork. The
effects are properties of the document, so View > Disable Effects only changes the preview — it is
not saved. Turn them off on the group (the background inspector offers only fill type and colour):
| Setting | Effect on flat artwork |
|---|---|
Translucency |
The one that matters. Lightens and tints everything — pure white renders around 87 % grey. Off restores the source colours exactly. |
Shadow |
Subtle darkening gradient towards the bottom. Set to None for an exact match. |
Specular |
Highlight along layer edges. Invisible on full-bleed artwork, visible on cut-out logos. |
Background fill |
Standard Gradient derives a gradient from the chosen colour. Use Solid with the exact brand colour, or ignore it when the artwork is full-bleed and opaque. |
With those off, the compiled icon is pixel-identical to the source image apart from two things that belong to the platform and cannot be turned off: the squircle mask, and a light bevel along the border roughly 2 % of the icon’s width. The dark, tinted and clear appearances are always generated as well — they are the user’s choice on the device, not the app’s.
The same settings can be edited directly in the package’s icon.json, which is more reliable than
clicking through the inspector and survives in version control:
"shadow" : { "kind" : "none", "opacity" : 0 },
"specular" : false,
"translucency" : { "enabled" : false, "value" : 0 }
Both keys of shadow and translucency are required; omitting opacity or value makes the document
fail to load. A render can be checked without a full build using the CLI bundled with Icon Composer:
"/Applications/Xcode.app/Contents/Applications/Icon Composer.app/Contents/Executables/ictool" \
AppIcon.icon --export-image --output-file preview.png \
--platform iOS --rendition Default --width 1024 --height 1024 --scale 1
How it works
Assets/Scripts/Core/Editor/IOSAppIconPostProcessor.cs runs on [PostProcessBuild] and:
-
Copies
Assets/UI/Icons/appIcon/ios/composer~/AppIcon.icontoUnity-iPhone/AppIcon.iconin the generated project, skipping.metaand.DS_Storefiles that Unity or Finder may have left inside it. -
Deletes
Unity-iPhone/Images.xcassets/AppIcon.appiconset. -
Adds the package to the main target’s Resources build phase and sets
ASSETCATALOG_COMPILER_APPICON_NAME. -
Rewrites the file reference’s
lastKnownFileTypetofolder.iconcomposer.icon.
The last step is the one non-obvious part. Unity’s PBXProject writer only knows the file types that
shipped with it, so it stamps the unknown package as a plain file and exposes no API to override
that; the single file-reference line is therefore patched in the written project.pbxproj. The value
is Xcode’s own, from StandardFileTypes.xcspec, where folder.iconcomposer.icon is listed as an input
of the asset catalog compiler. The build system does fall back to the extension and compiles the icon
even without it, but the explicit type is what Xcode itself writes — it keeps the package opening as an
Icon Composer document in the generated project and keeps the build off an undocumented fallback.
PBXProject preserves the value, so later post-processors rewriting the project do not lose it.
The step is safe to re-run: an append build finds the existing file reference and only refreshes the copied package and the build settings.