Friday, 24 July 2026

How to Build Unity Games for iOS: Xcode Setup, Player Settings, and App Store Submission

iOS builds are more complicated than Android builds. Not dramatically more, but there is one constraint that catches every Windows developer off guard: Xcode is only available on macOS, so if your development machine does not run macOS, you cannot build an iOS application locally. You need either a Mac or Unity Build Automation, which handles the Xcode step in the cloud.

That aside, the Unity side of the setup is straightforward. The hard parts are almost always Apple-specific — provisioning profiles, signing certificates, bundle identifiers that have to match exactly across three different places, and Xcode's occasional tendency to refuse to trust a connected device for no obvious reason. None of those are Unity problems. They are Apple problems.

This guide covers the full pipeline: installing iOS Build Support, configuring Player Settings correctly, running on a physical device for testing, signing for the App Store, and fixing the errors that show up on every first iOS build. It pairs directly with the Android Build guide from this series — same structure, iOS-specific details throughout.



What You Need Before Starting

  • A Mac running macOS. Xcode only runs on Mac. An M1/M2/M3/M4 Mac Mini is the cheapest viable option if you are buying specifically for iOS development — they run Xcode without any issues and are significantly faster than older Intel Macs for IL2CPP builds.
  • Xcode 15 or later. Unity recommends Xcode 15 or later for iOS development. Apps submitted to the App Store must be built with Xcode 16.0 or later and the iOS 18 SDK. Install Xcode from the Mac App Store — it is free but large (around 15GB).
  • iOS Build Support module installed through Unity Hub.
  • An Apple ID for local device testing (free). An Apple Developer Program membership ($99/year) for App Store distribution.
  • A physical iPhone or iPad for testing. The iOS Simulator in Xcode runs on your Mac but does not test actual GPU performance, touch input, or device-specific behavior accurately enough to replace real hardware.

If you are on Windows and cannot access a Mac, Unity Build Automation can build iOS applications for you in the cloud. You still need to register for an Apple Developer account, generate certificates and provisioning profiles through the Apple Developer portal, and upload your credentials to Unity Build Automation. That workflow is worth knowing about but is more advanced than a local build — for a first iOS build, a Mac is the significantly simpler path.


 

Part 1: Installing iOS Build Support

  1. Open Unity Hub.
  2. Go to the Installs tab.
  3. Click the gear icon next to your Unity version and select Add Modules.
  4. Check iOS Build Support.
  5. Click Install and wait for the download.

Unlike Android, iOS Build Support has no sub-modules to check — there is no separate SDK or NDK to worry about. Apple's toolchain lives entirely in Xcode. The Unity module just adds the ability to generate an Xcode project from your Unity project. Xcode then handles the actual compilation.

After installation, confirm it worked by opening Unity and going to File > Build Settings. iOS should now appear in the platform list. If it is missing or shows "Install with Unity Hub," the module did not install correctly — go back to Hub and try again.

Part 2: Switching Platform to iOS

  1. In Unity, go to File > Build Settings.
  2. Select iOS from the platform list.
  3. Click Switch Platform.

This reimports your assets for iOS — same process as Android, same warning about it taking a while on larger projects. After the switch, the iOS icon appears next to scene files in the Project window confirming the active platform changed.

Part 3: Player Settings That Matter

Open through Edit > Project Settings > Player, then select the iOS icon tab.

Bundle Identifier

This is the most important iOS-specific setting and the one that causes the most pain when it is wrong. The bundle identifier is the unique ID for your app across Apple's entire ecosystem — it must match exactly between Unity, Xcode, and the Apple Developer portal. If any of the three disagree, the build fails or the app cannot be signed.

Format: com.yourcompany.gamename — same reverse domain notation as Android's package name, same rules: lowercase, no spaces, globally unique for App Store distribution.

Set this before doing anything else. Changing it mid-project is possible but requires updating it in multiple places simultaneously, which is how mismatches happen.

Signing Team

This is your Apple Developer Team ID. You can leave it blank for local device testing with a free Apple ID, but it must be set for any App Store build. It appears as a dropdown once you have signed into Xcode with your Apple ID — set it in Unity Player Settings to match what Xcode will use, or let Xcode manage it automatically by checking "Automatically manage signing" in the Xcode project settings.

Target iOS Version

The minimum iOS version your app supports. Setting it lower means more devices can install it; higher lets you use newer iOS features. For most games in 2026, iOS 15 or 16 as the minimum covers the vast majority of active iPhones while still giving access to modern APIs. Check Apple's App Store analytics for current device distribution if you want data to back the decision.

Architecture

Set to ARM64. All iPhones and iPads from 2017 onward use 64-bit ARM processors. There is no reason to support ARMv7 for new projects — Apple dropped 32-bit app support in iOS 11. ARM64 only.

Scripting Backend

IL2CPP is the only option for iOS — Mono is not supported on iOS due to Apple's restrictions on just-in-time compilation. This is already the default. You cannot accidentally use Mono on iOS; Unity will not let you.



Part 4: Generating the Xcode Project

Unity does not compile your game directly into an iOS app. Instead, it generates an Xcode project, and then Xcode builds that project into the final application. This two-step process is important to understand because it means you will sometimes need to make changes in Xcode rather than in Unity.

  1. In Build Settings, click Build (not Build and Run — we will get to that).
  2. Choose an output folder. Create a new folder called something like "iOSBuild" outside your Unity project folder.
  3. Unity generates the Xcode project files in that folder. It does not install anything to a device yet.
  4. Navigate to that folder in Finder and open the .xcodeproj file. Xcode opens the generated project.

If you use Build and Run instead of Build, Unity generates the project AND tells Xcode to compile and install it to a connected device in one step. Build and Run is faster once everything is set up correctly. Use Build first until you have confirmed the Xcode project generates without errors.

The Replace vs Append Dialog

Every subsequent build to the same output folder shows a dialog asking whether to Replace or Append the existing Xcode project.

  • Replace — completely overwrites the Xcode project. Use this during normal development. Any manual changes you made to the Xcode project are lost.
  • Append — merges Unity's new output into the existing Xcode project, preserving manual changes you added. Use this if you have edited the Xcode project directly to add frameworks or capabilities that Unity does not handle automatically.

Most beginners should always choose Replace until they have a specific reason to edit the Xcode project directly.

Part 5: Testing on a Physical Device

With a Free Apple ID (No Developer Program)

  1. Open the generated .xcodeproj in Xcode.
  2. Connect your iPhone or iPad via USB.
  3. In Xcode, go to Signing & Capabilities and sign in with your Apple ID if prompted.
  4. With a free Apple ID, Xcode creates a personal team that allows you to install apps on up to 3 devices with a 7-day certificate validity. The app will stop working after 7 days and needs to be reinstalled.
  5. Select your connected device from the device dropdown at the top of Xcode.
  6. Press the Play button (or Cmd+R) to build and install.
  7. The first time, your iPhone will show a prompt about trusting the developer — go to Settings > General > VPN & Device Management and trust your Apple ID there.

The 7-day limit is annoying during active development but works fine for quick tests. The Apple Developer Program ($99/year) removes the limit and enables App Store distribution.

With an Apple Developer Program Account

Log into your Apple Developer account at developer.apple.com, register your device's UDID, and create a Development provisioning profile for your bundle identifier. In Xcode, under Signing & Capabilities, either let Xcode manage signing automatically (simplest) or manually select the provisioning profile you created. The certificate validity extends to one year rather than seven days.



Part 6: App Store Submission

Getting to the App Store requires a few steps beyond just building correctly.

Archive the Build in Xcode

  1. In Xcode, set the target device to Any iOS Device (arm64) — not a specific connected device.
  2. Go to Product > Archive.
  3. Xcode builds the app and adds it to the Archives list in the Organizer window.

Upload to App Store Connect

  1. In the Xcode Organizer, select the archive and click Distribute App.
  2. Choose App Store Connect and follow the wizard.
  3. Xcode validates and uploads the build to App Store Connect.

TestFlight First

Before submitting for App Store review, test through TestFlight. Any build uploaded to App Store Connect is automatically available for TestFlight testing with external testers. Testing with real users on TestFlight before App Store submission catches device-specific bugs that neither the Unity editor nor Xcode's simulator will surface.

App Store review typically takes 24 to 48 hours for a new app with no prior rejections. Apple reviews both the app's functionality and its metadata — screenshots, description, and privacy disclosures. Rejections almost always come with an explanation and are fixable.

Common Errors and How to Fix Them

Error: "No profiles for [bundle identifier] were found"

Cause: The bundle identifier in Unity Player Settings does not match what is registered in the Apple Developer portal, or no provisioning profile exists for this identifier.

Fix: Confirm the bundle identifier matches exactly — including case — across Unity, Xcode, and the Apple Developer portal. If using automatic signing, let Xcode create the profile. If using manual signing, create the profile at developer.apple.com and download it.

Error: "IL2CPP C++ code builder is unable to build C++ code. In order to build C++ code for Mac, you must have Xcode installed."

Cause: Xcode is installed but its Command Line Tools are not configured, or Xcode is installed in a non-standard location.

Fix: Open Terminal and run sudo xcode-select --switch /Applications/Xcode.app to point the system to the correct Xcode location. Also open Xcode once and accept the license agreement — it is required before any command-line tools work.

Error: Build succeeds but app crashes immediately on device.

Cause: A script or plugin has a runtime error that does not surface in the editor, or a missing capability (like Push Notifications or Camera access) causes an immediate termination.

Fix: Connect the device to Xcode, go to Window > Devices and Simulators, select your device, and open the device log while reproducing the crash. The actual exception appears there. For missing capabilities, add them under Signing & Capabilities in the Xcode project.

Error: "Untrusted Developer" when opening the app on device.

Cause: The signing certificate is from a free Apple ID and has not been trusted on this device yet.

Fix: On the iPhone, go to Settings > General > VPN & Device Management, find your Apple ID under Developer App, and tap Trust.

Error: App Store submission rejected for privacy reasons.

Cause: The app uses a system API (camera, microphone, location, contacts) without including the corresponding privacy usage description string in Player Settings, or without declaring data collection in App Store Connect's privacy nutrition label.

Fix: In Unity Player Settings > Other Settings, fill in every usage description string for APIs your app uses. In App Store Connect, complete the App Privacy section accurately before submission. Apple's rejections here are specific — they tell you exactly which API triggered the issue.



iOS vs Android Build: Key Differences

Area iOS Android
Build machine requirement Mac required for local builds Windows, Mac, or Linux
Build output Xcode project, then .ipa via Xcode APK or AAB directly from Unity
Scripting backend IL2CPP only — Mono not supported Mono for dev, IL2CPP for release
Signing for device testing Free Apple ID, 7-day certificate Debug keystore auto-generated, no expiry
Store distribution fee $99/year Apple Developer Program $25 one-time Google Play fee
Review process Manual review, 24-48 hours typical Largely automated, hours to days
Primary graphics API Metal (Apple's API, only option) Vulkan or OpenGL ES

Best Practices

  • Set the bundle identifier before your first build. Changing it later means updating it in Unity, Xcode, and the Apple Developer portal simultaneously — missing any one causes signing failures.
  • Use automatic signing in Xcode during development. Switch to manual signing only when you need specific provisioning profiles for distribution.
  • Test on at least two physical devices before App Store submission — an older model and a current one. Performance that looks fine on an iPhone 15 can be unacceptable on an iPhone XR that your players still use.
  • Archive builds in Xcode using the Any iOS Device (arm64) target, not a connected device. Archiving to a specific device creates a build that cannot be distributed.
  • Use TestFlight for beta testing before App Store submission. It finds real-device bugs that nothing else catches.
  • Fill in all privacy usage description strings in Player Settings before building. Missing them causes App Store rejection, and adding them requires a full rebuild and resubmission.
  • Keep your Apple Developer certificates backed up. Certificate expiration mid-submission cycle is a preventable headache.

What Comes Next

Getting the build pipeline working is the foundation. Once you have a device build running, the next iOS-specific considerations are performance profiling using Xcode's Instruments tool (far more detailed than Unity's Profiler for GPU-side issues on Metal), implementing iOS-specific features like Game Center achievements and leaderboards through Unity's Services, and setting up automatic builds using Unity Build Automation or a CI system like GitHub Actions so you are not manually triggering Xcode builds every time you need a test build.

The Mobile Optimization guide from this series covers the Unity-side performance work. The GitHub Actions guide teased at the end of the Git tutorial covers the automation side. Both are worth reading once this build pipeline is stable.

Next Topics To Learn

Wednesday, 22 July 2026

How to Use Leonardo AI for Game Development: Free Concept Art, 3D Textures, and Custom Models

Every AI image guide in this series has mentioned Leonardo AI as the free alternative to try before paying for Midjourney. That framing undersells it. Leonardo AI is not a consolation prize — it has features that Midjourney and DALL-E do not have at any price, and a free tier generous enough for serious visual development work.

The features that make it specifically interesting for game developers: 3D texture generation that creates albedo, normal, and roughness maps directly from text prompts, custom model training on your own reference images, and a token-based free tier that resets daily rather than expiring at the end of a month. None of those exist in Midjourney. Stable Diffusion can do all of it but requires significant technical setup. Leonardo does it through a web interface with no installation.

One thing worth knowing upfront: Leonardo AI was acquired by Canva in 2025. The product has continued developing under Canva's ownership and the feature set has expanded, but it is worth keeping in mind when evaluating long-term platform stability. The pricing and feature set described in this guide reflect the current state as of mid-2026.



Pricing: What the Free Tier Actually Gets You

Most AI tool pricing sections bury the free tier in caveats. Leonardo's free tier is different enough that it deserves an honest upfront assessment.

The free plan gives you 150 tokens per day, which resets every 24 hours. A standard image generation using the Leonardo Diffusion XL model costs 4-6 tokens, which means roughly 25-37 images per day. That is a meaningful daily allowance — enough for active concept art exploration during visual development, not just enough to click around and evaluate the interface.

The catch on the free tier: free generations are public, meaning anyone browsing Leonardo's community feed can see what you generate. If your game's visual direction is confidential, you need a paid plan for private generations.

Plan Monthly Price Annual Price Tokens/Month Private Images Custom Model Training
Free $0 $0 150/day (~4,500/month) No — all public No
Apprentice $12 $10/month ($120/year) 8,500 Yes 1 LoRA slot/month
Artisan $30 $24/month ($288/year) 25,000 Yes 20 personal model slots
Maestro $60 $48/month ($576/year) 60,000 Yes 50 personal model slots

When fast tokens run out, Artisan and Maestro subscribers can switch to relax mode, which uses basic models at no token cost but joins a lower-priority queue. Relax mode is not available on Apprentice or Free plans.

The honest recommendation for a solo developer: start on the free tier for at least a week before paying anything. If 150 tokens per day is enough for your workflow and you do not need private images, the free tier is genuinely sustainable long-term. Apprentice at $12/month is one of the cheapest premium AI image generators available when you do upgrade — significantly cheaper than Midjourney Standard at $30.


The Models Worth Knowing

Leonardo AI has its own proprietary models alongside access to third-party community models. The ones that matter most for game development:

Model What It Produces Game Dev Use Case
Phoenix Leonardo's current flagship model. Produces highly detailed, coherent images with strong prompt adherence. Character concepts, environment art, promotional material. The default starting point for most generations.
Leonardo Diffusion XL SDXL-based model with Leonardo's refinements. Faster and cheaper than Phoenix. High-volume concept exploration where speed and token cost matter more than maximum quality.
PhotoReal v2 Hyper-realistic photography-style output. Realistic environment references, character face references for later LoRA training.
Anime / Illustration models Several community fine-tuned models for anime and stylized illustration styles. 2D game art, mobile game UI character art, visual novel assets.

Alchemy and Prompt Magic v2/v3 are not models but processing pipelines that run on top of any model. Alchemy unlocks higher quality output and the Alchemy Refiner at no additional per-use charges on Apprentice and above. They cost more tokens per generation but produce meaningfully better results on character faces and fine detail. Worth enabling for final concept iterations, not for broad style exploration where you are generating dozens of variations.

Part 1: Concept Art Workflow

The basic text-to-image workflow is similar to Midjourney: open a generation canvas, enter a prompt, pick a model, generate. The interface is more button-heavy than Midjourney's clean chat-style interface, but everything is visible and labeled rather than hidden behind command syntax.

A few Leonardo-specific settings that change the result meaningfully:

Guidance Scale

This is equivalent to CFG Scale in Stable Diffusion — how strictly the model follows the text prompt. Higher values (12-20) produce images that literally match the prompt but can look stiff or over-saturated. Lower values (6-9) give the model more creative latitude and often produce more interesting images for concept exploration. Start around 7-10 and adjust based on whether your prompt's details are being followed correctly.

Image2Image

Upload a reference image and generate variations from it. This is the feature that closes the gap between "generate random concepts" and "iterate toward a specific design." Draw a rough sketch in any drawing app, upload it, and use Image2Image to generate polished versions while keeping the general composition and proportions. Works with any model.

I spent a full day trying to get Midjourney to produce a specific character silhouette through prompt iteration and never quite got there. Took the rough sketch into Leonardo's Image2Image, ran it through Phoenix with the right denoising strength, and had the silhouette I wanted in three generations. Different category of precision.

Negative Prompts

Available directly in the interface unlike Midjourney where negative prompting (--no) is less reliable. Standard negative prompt for game concept art: blurry, deformed, extra limbs, bad anatomy, watermark, text, signature, low quality, oversaturated.


 

Part 2: 3D Texture Generation

This is the feature that separates Leonardo AI from every other tool covered in this AI Tools series. Leonardo includes a specialized 3D texture generation tool that creates albedo, normal, and roughness maps directly from text prompts — essential maps for PBR materials in Unity and Unreal.

Finding it: in the left sidebar of Leonardo's interface, look for 3D Texture Generation under the Tools section.

How It Works

  1. Enter a texture description: "rough mossy stone wall, medieval, aged" or "worn wooden planks, grey paint peeling, weathered."
  2. Choose a resolution (512x512 for draft testing, 1024x1024 for usable assets).
  3. Generate. Leonardo produces a set of maps: albedo (base color), normal map (surface detail), and roughness map (reflectivity variation).
  4. Download the map pack as individual files.
  5. In Unity, create a material using Standard (Built-In) or URP Lit shader, assign the albedo to Albedo/Base Color, the normal map to Normal Map, and the roughness map to Smoothness/Roughness.

The results are not perfect. Complex organic surfaces like human skin or fur do not generate well. Very regular geometric patterns like brick or tile come out better from procedural texture tools. Where Leonardo's texture generation shines is worn, irregular surfaces — stone, wood, rust, fabric, aged paint — exactly the kind of surfaces that populate most game environments.

For the crate from the Blender guides in this series: a "rough weathered wooden planks with metal corner reinforcements" prompt produces a usable texture pack in minutes without needing Substance Painter or any dedicated texture tool.



Part 3: Custom Model Training (LoRA)

This is Leonardo's most powerful feature for maintaining visual consistency across a game project — training a custom model on your own reference images so every generation automatically inherits that visual style without prompt engineering.

Available on Apprentice and above (one training slot per month on Apprentice, 20 slots on Artisan).

Training a Character LoRA

  1. Collect 10-20 high-quality reference images of the same character or style from consistent angles, in good lighting, with no busy backgrounds.
  2. In Leonardo, go to Training & Datasets in the left sidebar.
  3. Create a new dataset and upload your reference images.
  4. Click Train Model, name it, select the base model (Phoenix or Leonardo Diffusion XL), and set the training resolution to match your reference images.
  5. Start training. It runs on Leonardo's servers — typically 20-40 minutes depending on image count and resolution.
  6. Once complete, the model appears in your model selector and can be used in any generation.

With a trained LoRA, prompting "CHARACTER NAME in a combat stance, fantasy armor, dramatic lighting" produces consistent character identity across multiple generations in a way that neither Midjourney nor basic Stable Diffusion can match without the same training step.

The main limitation: 10-20 training images is not much data. The more consistent and diverse your reference set (different poses, same character), the better the model learns the character rather than overfitting to a specific pose or composition from the training set.

Leonardo AI vs Midjourney: Where Each Wins

Category Leonardo AI Midjourney
Free tier 150 tokens/day, genuinely useful No free tier in 2026
Starting paid price $12/month (Apprentice) $10/month (Basic, ~200 images total)
Image quality ceiling High, especially with Alchemy and Phoenix Higher for pure artistic illustration work
3D texture generation Yes — albedo, normal, roughness maps No
Custom model training Yes — LoRA training on paid plans No
Image2Image Yes — strong and accessible Limited through --cref and variation tools
Privacy on free tier No — all public N/A — no free tier
Best for Developers who need game-specific features, a free tier, or custom style training Developers who prioritize pure image quality and have no interest in technical features



What Does Not Work Well

The token system is confusing until you understand it, and even then it can be frustrating. Premium features like Alchemy and high-resolution generation consume significantly more tokens than standard generations. A free tier user who enables every premium setting will burn through 150 daily tokens in five or six images. Understanding token cost before enabling features saves a lot of disappointment.

The interface has more options than Midjourney and is less intuitive for a complete beginner. The model selector, Alchemy toggle, Prompt Magic settings, and Image2Image controls all exist in different parts of the interface and the relationship between them is not immediately obvious. Plan on spending an hour exploring the interface before expecting professional results.

Community models from third-party creators vary enormously in quality. The platform curates a featured selection but the broader library includes models that produce inconsistent or low-quality results. Stick to Leonardo's own models (Phoenix, Diffusion XL, PhotoReal) and community models with high ratings and large generation counts until you know what you are looking for.

Video generation is available but generating a 5-second clip using the best video model costs 2,500 tokens — on the Artisan plan at $30/month that is roughly $3 per clip in token value. Dedicated video tools like Runway are more cost-effective if video is your primary output.

Practical Workflow: Combining With Blender and Unity

The natural pipeline for a solo Unity developer using Leonardo:

  1. Generate character and environment concept art using Phoenix or Diffusion XL with Alchemy enabled, using Image2Image on rough sketches from the Blender modeling workflow.
  2. Use 3D Texture Generation for surface materials on models built in the Blender guides — stone, wood, metal, fabric.
  3. Download the map pack, import into Unity as textures, and assign to materials using the Unity PBR material system.
  4. If a character design is established, train a LoRA on the approved concept art so all subsequent character generation inherits that design without prompt repetition.

This pipeline keeps Midjourney's use case for pure artistic illustration while using Leonardo for the technical, game-specific work it does better. Using both tools for what each does best is more effective than picking one and forcing it to cover everything.

Getting Started: The First Session

Create an account at leonardo.ai — no credit card required. The interface asks you to select your use case on first login. Choose Game Development or Concept Art for the most relevant model recommendations on the home screen.

Start with the free tier for at least a week before evaluating paid plans. Generate at least fifty images across different models and settings before forming an opinion about quality. The first ten generations from any new AI tool are not representative of what it produces once you understand its quirks.

The 3D texture generation tool and Image2Image are worth finding on day one — they are the features that most directly differentiate Leonardo from the other tools in this series and are the clearest demonstration of why it is worth trying separately from Midjourney.

Common Issues and Fixes

Token counter shows zero but the day has not ended.

Premium features like Alchemy, high resolution, and multiple samples consume tokens faster than standard settings. Check your current token balance in the top navigation bar. Tokens reset at the same time each day, not at midnight in your local timezone — the reset time is shown in the account panel.

Generated images look low quality or blurry compared to examples.

Alchemy is likely disabled. Enable it in the generation settings (it shows as a toggle above the generate button) and confirm you are using a current model like Phoenix rather than an older community model. Quality also scales with resolution — generating at 512x512 with premium settings still produces lower quality than 1024x1024 at standard settings.

Custom model training fails or produces images that look nothing like the reference.

Reference image quality and consistency are the main factors. Images with varied backgrounds, different characters in the same set, or inconsistent lighting confuse the training process. Re-prepare the dataset with cleaner, more consistent references and retrain. Also confirm the training resolution matches the resolution of your reference images.

3D texture outputs look tileable but show visible seams when applied in Unity.

Enable Make Seamless in the texture generation settings before generating. For textures that are already generated, Unity's texture import settings include a Wrap Mode setting — ensure it is set to Repeat rather than Clamp, and enable the seamless tiling option in the texture importer.



Next Topics To Learn

  • Midjourney for Game Developers — the higher-quality-ceiling alternative to Leonardo for pure concept art work, at a higher price point with no free tier.
  • Stable Diffusion for Game Developers — the free, locally-run alternative that provides similar custom model training (LoRA) and texture generation capabilities without any subscription cost, at the price of technical setup.
  • ControlNet for Game Developers — pose and composition control that works alongside Leonardo's Image2Image workflow for precise character generation.

How to Use Figma for Game UI Design: Mockup, Export, and Bring It Into Unity

Most Unity developers design UI directly in the Unity Canvas. You drag in a Panel, add some buttons, resize things until they look roughly...