Skip to main content
Tutorials

Build a Unity game for iOS on Windows and test it on your iPhone

Unity on Windows can export an Xcode project for iOS, but building, installing and packaging it usually means moving to a Mac. This tutorial shows how to take the exported project on the same Windows PC, build it into an app, test it on your iPhone and produce an .ipa. You need an Apple Developer account, an iPhone and a USB cable, and you need to have installed KXBuild.

Switch to the iOS platform

Open the project in Unity and go to File > Build Profiles (File > Build Settings in Unity 2022 and earlier). Select iOS on the left and click “Switch Platform”. The first switch reimports assets, which takes a while for large projects.

“Build And Run” calls Xcode on the local machine, so it doesn’t work on Windows. This tutorial uses only “Build”.

Configure Player Settings

Click “Player Settings” in the Build Profiles window, or go to Edit > Project Settings > Player, and switch to the iOS tab. The settings below directly affect installing on a device and submitting to the App Store. In Unity 6, check Override Default Bundle Identifier before you can edit Bundle Identifier.

Location Setting Recommended value
Other Settings > Identification Bundle Identifier Matches the App ID registered in your developer account, for example com.example.mygame
Other Settings > Identification Version The version shown on the App Store, for example 1.0.0
Other Settings > Identification Build The build number. Each upload to App Store Connect needs a higher one than the last
Other Settings > Identification Signing Team ID Your developer account’s Team ID
Other Settings > Configuration Scripting Backend IL2CPP, the only one iOS supports
Other Settings > Configuration Architecture ARM64
Other Settings > Configuration Target SDK Device SDK. A project exported with Simulator SDK can’t be installed on a device
Other Settings > Configuration Target minimum iOS Version The oldest iOS version you want to support. The default is fine too
Other Settings > Configuration Camera Usage Description Required if you use the camera
Other Settings > Configuration Microphone Usage Description Required if you use the microphone
Other Settings > Configuration Location Usage Description Required if you use location

Usage descriptions are written into the exported project’s Info.plist. If the game uses the camera, microphone or location without a description, it crashes as soon as it makes the call, and App Review rejects it.

Put the .p12 certificate and .mobileprovision provisioning profile for signing in the keychain folder. During development, use an Apple Development certificate and a Development provisioning profile that includes this iPhone’s UDID. For how to get and place them, see Certificates and signing.

Export the Xcode project

Click “Build” in the Build Profiles window and choose an empty folder, such as D:\u\mygame. Use a short path for the export folder. The project Unity exports nests deeply, and a deep path easily runs into path-too-long errors on Windows.

While testing, you can check “Development Build” for more complete logs on errors and a connection to the Unity Profiler. Remember to uncheck it before your production build.

After the export, the folder contains Unity-iPhone.xcodeproj. If the project uses plugins with iOS dependencies, such as Firebase or Google Mobile Ads, the folder also has a Podfile. Run pod install once in the export folder, which creates Unity-iPhone.xcworkspace.

1cd D:\u\mygame
2pod install

For more on CocoaPods, see Develop iOS apps with CocoaPods on Windows.

Open in VS Code and run doctor

In VS Code, open the export folder D:\u\mygame with File > Open Folder…. The KXBuild view lists its project and targets. The app target is Unity-iPhone. The other one, UnityFramework, is a framework it depends on and is compiled along with it.

The first time you open it, run doctor. It checks what the build needs and fixes anything missing. Use either of these.

  • VS Code extension. In the title bar of the KXBuild view, open the ··· menu and run Doctor (fix environment).
  • Command line. Run the command below in the export folder.
1kxbuild doctor .\Unity-iPhone.xcodeproj

Test on your iPhone

Connect the iPhone with a cable, unlock it and tap Trust in the Trust This Computer prompt, then turn on Developer Mode in Settings > Privacy & Security > Developer Mode. The iPhone restarts once. For drivers and iPhone settings, see Set up your device.

Select the iPhone in the KXBuild view and press F5. KXBuild builds, signs, installs and launches the game, then attaches the debugger. The first compile of the C++ code generated by IL2CPP takes a while, and later builds are incremental. The first time you debug on a given iOS version, KXBuild also downloads its device symbols. It’s a few GB, but only once.

While the game runs, output from Debug.Log and the like appears in the KXBuild Console channel of the VS Code Output panel, and the build log in the KXBuild channel. Open the Output panel with Ctrl+Shift+U and switch channels from the dropdown at the top right.

Each kind of code uses its own debugger.

  • Native code (Objective-C plugin code in the export folder). Set breakpoints in VS Code. See Run and debug.
  • C# scripts. Use Unity’s own debugger. Write them in Unity as usual and export again after changes.

To reinstall without recompiling, use KXBuild: Run in the title bar of the KXBuild view. It installs the output of the last build and launches it.

Export again after C# changes

After changing C# scripts, scenes or assets, Build again in Unity to the same folder. When the folder exists, Unity asks whether to Append or Replace.

Choice When to use it
Append Day-to-day iteration. Updates what Unity generates and keeps your changes to the exported project
Replace After upgrading Unity, or when the exported project has build errors you can’t explain. The whole folder is regenerated and manual changes are lost

After Replace, run pod install again if there’s a Podfile, then run doctor once more. After exporting, go back to VS Code and press F5. KXBuild recompiles only what changed.

For native changes you want to keep, such as extra Info.plist keys or build settings, write them in at export time with a Unity PostProcessBuild script so Replace doesn’t lose them. For one-off changes, edit the exported project directly with the Property List Editor and Project Settings Editor.

Check performance

Sample frame rate, CPU and memory on the device with kxdevice to get numbers close to what players see. Install a Release build before measuring.

1kxbuild build .\Unity-iPhone.xcodeproj -c Release -t Unity-iPhone --install
2kxdevice instruments sysmon -i 1

sysmon prints CPU usage continuously. For dropped frames, memory growth and hot functions, use fluidity, allocations and stackshot. See Performance profiling for the full table and usage. Unity’s built-in Profiler is better for script and rendering timings, and the two work well together.

Build a Release .ipa

Before submitting, make sure Build in Player Settings is higher than in your last upload, and that the keychain folder has an Apple Distribution certificate and an App Store provisioning profile. If you changed Player Settings, export again.

Use either of these.

  • VS Code extension. Switch the configuration to Release in the Build configuration node of the KXBuild view, then run KXBuild: Build from the Command Palette.
  • Command line. The target is always Unity-iPhone. Run the command that fits your export folder.

For an export folder without a Podfile, run this.

1kxbuild build .\Unity-iPhone.xcodeproj -c Release -t Unity-iPhone

For an export folder with a Podfile where you’ve already run pod install, run this.

1kxbuild build .\Unity-iPhone.xcworkspace -c Release -t Unity-iPhone

If the project’s Release configuration doesn’t specify a distribution certificate, add -D CODE_SIGN_IDENTITY="Apple Distribution" on the command line to override it for this build.

When the build finishes, the .ipa is in the build folder of the export folder. Upload it to App Store Connect with Appuploader on Windows. When processing finishes, it appears on the TestFlight page. Send it to testers first, then submit it for review. See Release and App Store submission.

FAQ

scheme or target not found. The app target in a Unity export is Unity-iPhone. On the command line, pass -t Unity-iPhone.

File name too long or file not found. Move the export folder to a short path such as D:\u\mygame and Build again.

The build can’t find Firebase or other dependencies. Run pod install in the export folder and build Unity-iPhone.xcworkspace.

The game quits right after launch. First check that the usage descriptions are filled in, then look at device logs and crash reports. See Run and debug and Troubleshooting.