All-in-One Solution for Indie Game Development · Empowering Indie Developers' Dreams
📖 Documentation • 🚀 Quick Start
🌐 Language: English | 简体中文 | 繁體中文 | 日本語 | 한국어
An editor tool that automatically configures Xcode projects after Unity iOS builds. Declaratively manage all Xcode settings — Info.plist, frameworks, libraries, build properties, Capabilities, CocoaPods sources, localizations, and more — through a JSON config file, with no manual Xcode operations needed.
- Info.plist — Supports string, boolean, integer, array, dictionary types with recursive writing
- System Frameworks/Libraries — Automatically add or remove
.framework/.tbd - Build Properties — Set, append, or remove Build Settings (e.g.
ENABLE_BITCODE,GCC_ENABLE_OBJC_EXCEPTIONS) - Capabilities — In-App Purchase, Game Center, Push Notifications, Sign In with Apple, Background Modes, iCloud, App Groups, Associated Domains
- Localization — Auto-generate
.lproj/InfoPlist.stringswith multi-language app name support - CocoaPods — Replace Podfile default source, support multiple mirror sources
- XcScheme — Inject environment variables and launch arguments
- Files/Folders — Auto-copy to Xcode project and add to compilation, recognize
.framework/.bundle - Compile Flags — Set compile options for specific source files
- Linker Flags — Configure
OTHER_LDFLAGSetc. - Run Path Search Paths — Configure runtime search paths
- Code Signing — Configure Team ID, bundle identifier, code sign identity, and provisioning profile
- Multi-Config Merge — Support deep recursive merge of multiple
XCodeConfig.jsonfiles for multi-module collaboration
Choose one of the following methods:
Method 1: Edit manifest.json
Add to Packages/manifest.json under dependencies:
"com.gameframex.unity.xcode": "https://github.com/gameframex/com.gameframex.unity.xcode.git"Method 2: Package Manager Git URL
Unity Editor → Window → Package Manager → Add package from git URL, enter:
https://github.com/gameframex/com.gameframex.unity.xcode.git
Method 3: Manual Download
Clone or download this repository and place it in your Unity project's Packages directory. It will be recognized automatically.
- Copy
Editor/XCodeConfigDemo.jsonfrom the package to any directory in your project - Rename it to
XCodeConfig.json - Modify the configuration as needed (see Configuration Reference below)
- Build the iOS project — the tool will automatically apply all settings
The configuration file must be named XCodeConfig.json. It can be placed anywhere in the project, and multiple files are supported (they will be merged automatically).
{
"signing": {},
"plist": {},
"environmentVariables": {},
"launcherArgs": [],
"podSource": [],
"localizations": [],
"capabilities": {},
"unityFramework": {},
"unityMain": {}
}| Field | Type | Description |
|---|---|---|
signing |
object | Code signing configuration (see below) |
plist |
object | Info.plist key-value pairs, values support any type |
environmentVariables |
object | XcScheme environment variables, both keys and values are strings |
launcherArgs |
string[] | XcScheme launch arguments list |
podSource |
string[] | CocoaPods source URLs, replaces Podfile default source |
localizations |
array | Localization configuration (see below) |
capabilities |
object | iOS app capability configuration (see below) |
unityFramework |
object | UnityFramework target configuration |
unityMain |
object | Unity-iPhone target configuration |
Both share the same structure, targeting UnityFramework and Unity-iPhone respectively:
{
"libs": { "+": [], "-": [] },
"frameworks": { "+": [], "-": [] },
"properties": { "=": {}, "+": {}, "-": {} },
"files": {},
"folders": {},
"filesCompileFlag": {},
"otherLinkerFlag": {},
"runPathSearchPaths": {}
}{
"libs": {
"+": ["libz.tbd", "libicucore.tbd"],
"-": ["libstdc++.tbd"]
}
}+Library names to add-Library names to remove
{
"frameworks": {
"+": ["WebKit.framework", "UserNotifications.framework"],
"-": []
}
}+Framework names to add-Framework names to remove
{
"properties": {
"=": { "ENABLE_BITCODE": "NO" },
"+": { "OTHER_CFLAGS": ["-flag1", "-flag2"] },
"-": { "UNUSED_FLAG": [""] }
}
}=Set properties (key-value pairs, overwrites existing values)+Append properties (array values are appended to existing list)-Remove properties
{
"files": {
"ios_libs.txt": "Classes/ios_libs.txt"
}
}- Key: File path in the Unity project (same level as
Assets) - Value: Relative path to copy to in the Xcode project
- If the destination exists, it will be deleted before copying
{
"folders": {
"XC": "Classes/XC"
}
}- Key: Folder path in the Unity project
- Value: Relative path to copy to in the Xcode project
- Automatically recognizes
.frameworkand.bundle - An error is raised if the destination already exists
{
"filesCompileFlag": {
"Classes/PluginBase/UnityViewControllerListener.mm": "-fobjc-arc"
}
}- Key: File path in the Xcode project
- Value: Compile flags to set
{
"otherLinkerFlag": {
"OTHER_LDFLAGS": "-ObjC"
}
}{
"runPathSearchPaths": {
"LD_RUNPATH_SEARCH_PATHS": "@executable_path/Frameworks"
}
}Applied to the Unity-iPhone (main) target only. All fields are optional.
{
"signing": {
"teamId": "XXXXXXXXXX",
"bundleId": "com.company.app",
"codeSignIdentity": "Apple Development",
"codeSignStyle": "Automatic",
"provisioningProfileSpecifier": ""
}
}| Field | Type | Description |
|---|---|---|
teamId |
string | Apple Developer Team ID (DEVELOPMENT_TEAM) |
bundleId |
string | App bundle identifier (PRODUCT_BUNDLE_IDENTIFIER) |
codeSignIdentity |
string | Code signing identity, options: Apple Development, Apple Distribution, iPhone Developer, iPhone Distribution |
codeSignStyle |
string | Signing style: Automatic or Manual |
provisioningProfileSpecifier |
string | Provisioning profile name (required for Manual mode) |
{
"capabilities": {
"inAppPurchase": true,
"gameCenter": false,
"pushNotifications": false,
"signInWithApple": false,
"backgroundModes": ["audio", "remote-notification"],
"iCloud": {
"keyValueStorage": false,
"iCloudDocument": false,
"customContainers": []
},
"appGroups": [],
"associatedDomains": []
}
}| Field | Type | Description |
|---|---|---|
inAppPurchase |
bool | In-App Purchase |
gameCenter |
bool | Game Center |
pushNotifications |
bool | Push Notifications |
signInWithApple |
bool | Sign In with Apple |
backgroundModes |
string[] | Background modes, options: audio, location, voip, newsstand, external, bluetooth, bluetooth-peripheral, fetch, remote-notification |
iCloud.keyValueStorage |
bool | iCloud Key-Value Storage |
iCloud.iCloudDocument |
bool | iCloud Document Storage |
iCloud.customContainers |
string[] | iCloud custom containers |
appGroups |
string[] | App Group identifiers |
associatedDomains |
string[] | Associated domains (Universal Links) |
{
"localizations": [
{
"languageCode": "en",
"validMap": [
{ "key": "CFBundleDisplayName", "value": "My Game" }
]
},
{
"languageCode": "zh-Hans",
"validMap": [
{ "key": "CFBundleDisplayName", "value": "我的游戏" }
]
}
]
}languageCode— ISO 639-1 language code (usezh-Hansfor Simplified Chinese /zh-Hantfor Traditional Chinese)validMap— Key-value pairs, each withkeyandvalue- Automatically generates
.lproj/InfoPlist.stringsand adds them to the project
Supports arbitrary nested levels. Common configuration:
{
"plist": {
"CFBundleURLTypes": [
{
"CFBundleTypeRole": "Editor",
"CFBundleURLSchemes": ["myapp"],
"CFBundleURLName": "com.example.myapp"
}
],
"NSAppTransportSecurity": {
"NSAllowsArbitraryLoads": true
},
"NSCameraUsageDescription": "Camera access is required for QR scanning",
"ITSAppUsesNonExemptEncryption": false
}
}You can place multiple XCodeConfig.json files in the project (e.g., each module maintains its own). During build, they are automatically discovered and deep-merged:
- Objects: Recursively merged (child keys merged layer by layer)
- Arrays: Union-merged (deduplicated)
- Scalars: Latter overwrites former
This allows Xcode configurations from multiple SDKs / modules to be managed independently without conflicts.
{
"signing": {
"teamId": "XXXXXXXXXX",
"bundleId": "com.company.app",
"codeSignIdentity": "Apple Development",
"codeSignStyle": "Automatic",
"provisioningProfileSpecifier": ""
},
"plist": {
"CFBundleURLTypes": [
{
"CFBundleTypeRole": "Editor",
"CFBundleURLSchemes": ["bbqgame"],
"CFBundleURLName": "com.smartdogx.bbq"
},
{
"CFBundleTypeRole": "Editor",
"CFBundleURLSchemes": ["wx5dfe430e96b395a6"]
}
],
"LSApplicationQueriesSchemes": [
"weixin", "wechat", "mqqapi"
],
"NSAppTransportSecurity": {
"NSAllowsArbitraryLoads": true,
"NSExceptionDomains": {
"qq.com": {
"NSIncludesSubdomains": true,
"NSThirdPartyExceptionAllowsInsecureHTTPLoads": true,
"NSThirdPartyExceptionRequiresForwardSecrecy": false
}
}
},
"NSCameraUsageDescription": "Camera access is required",
"NSMicrophoneUsageDescription": "Microphone access is required",
"NSPhotoLibraryUsageDescription": "Photo library access is required",
"ITSAppUsesNonExemptEncryption": false,
"NSUserTrackingUsageDescription": "This identifier will be used to deliver personalized ads"
},
"environmentVariables": {
"IDEPreferLogStreaming": "YES",
"OS_ACTIVITY_MODE": "disable"
},
"launcherArgs": ["-debug"],
"localizations": [
{
"languageCode": "en",
"validMap": [
{ "key": "CFBundleDisplayName", "value": "My Game" }
]
},
{
"languageCode": "zh-Hans",
"validMap": [
{ "key": "CFBundleDisplayName", "value": "我的游戏" }
]
}
],
"podSource": [
"https://mirrors.tuna.tsinghua.edu.cn/git/CocoaPods/Specs.git"
],
"capabilities": {
"inAppPurchase": true,
"gameCenter": false,
"pushNotifications": false,
"signInWithApple": false,
"backgroundModes": [],
"iCloud": {
"keyValueStorage": false,
"iCloudDocument": false,
"customContainers": []
},
"appGroups": [],
"associatedDomains": []
},
"unityFramework": {
"libs": {
"+": ["libicucore.tbd", "libz.tbd"],
"-": []
},
"frameworks": {
"+": ["WebKit.framework", "Security.framework"],
"-": []
},
"properties": {
"=": {
"ENABLE_BITCODE": "NO",
"GCC_ENABLE_OBJC_EXCEPTIONS": true,
"CLANG_ENABLE_OBJC_ARC": true
},
"+": {},
"-": {}
},
"filesCompileFlag": {},
"otherLinkerFlag": {
"OTHER_LDFLAGS": "-ObjC"
},
"files": {},
"folders": {}
},
"unityMain": {
"libs": {
"+": ["libz.tbd"],
"-": []
},
"frameworks": {
"+": ["WebKit.framework"],
"-": []
},
"properties": {
"=": { "ENABLE_BITCODE": "NO" },
"+": {},
"-": {}
},
"otherLinkerFlag": {
"OTHER_LDFLAGS": "-ObjC"
},
"files": {},
"folders": {}
}
}- The configuration file must be named
XCodeConfig.json, otherwise it will not be recognized - All code is under
#if UNITY_IOSconditional compilation, no impact on other platforms - The tool runs at
[PostProcessBuild(ushort.MaxValue)]priority, executing after all other post-processing - Folder copy raises an error if the destination exists; file copy deletes the existing destination first
- Unity 2017.1 or later
- iOS build target
- Xcode (automatically required when Unity exports iOS project)
