Version: Unity 6.6 Alpha (6000.6)
Language : English
Introduction to the Swift Xcode project type for iOS and tvOS
Structure of a Unity Xcode Swift project type

Migrate to a Swift Xcode project type

Migrate your existing Unity iOS project from the Objective-C project type to the new Swift project type.

Considerations when migrating to a Swift Xcode project type

Consider the following before migrating to a Swift Xcode project type:

  • Exporting a project as a Swift Xcode project sets the minimum supported iOS version to 16. This applies even if your project’s target version is lower.
  • Orientation handling during runtime behaves differently when using a Swift Xcode project type. For more information, refer to Manage screen orientation in Swift Xcode projects.
  • When migrating to a Swift Xcode project type, the following functionality isn’t currently available:
    • Unity as a Library
    • Full screen video

Create a Swift Xcode project type

Use the following steps to create a Swift Xcode project type:

  1. Navigate to Edit > Project Settings > Player.
  2. Select the iOS tab.
  3. From Other Settings > Configuration, set Xcode Project Type to Swift. This option is available for both iOS and tvOS.

Migrate post-process scripts for Swift Xcode projects

If you have post-process scriptsA piece of code that allows you to create your own Components, trigger game events, modify Component properties over time and respond to user input in any way you like. More info
See in Glossary
that modify Xcode project files, you must update them to support changes to the project structure.

Update the project path

The Xcode project file now uses a sanitized version of your Unity project’s name, rather than the static name Unity-iPhone.xcodeproj. To return the correct project path, use the PBXProject.GetPBXProjectPath method.

For example, update your code as follows:

// Before (Objective-C only):
string projPath = Path.Combine(pathToBuiltProject, "Unity-iPhone.xcodeproj/project.pbxproj");

// After (works for both Objective-C and Swift project types):
string projPath = PBXProject.GetPBXProjectPath(pathToBuiltProject);

Review your existing modifications to the .xcodeproj file to ensure they’re still required. For more information, refer to Structure of a Unity Xcode Swift project type.

Identify project types

To identify project types in your post-process scripts, use the UnityEditor.PlayerSettings.xcodeProjectType property. For example:

if (UnityEditor.PlayerSettings.xcodeProjectType == UnityEditor.XcodeProjectType.Swift) {
    // Swift project type specific modifications
} else {
    // Objective-C project type specific modifications
}

Migrate native plug-ins

With the introduction of the Swift project type, you must adapt your native plug-insA set of code created outside of Unity that creates functionality in Unity. There are two kinds of plug-ins you can use in Unity: Managed plug-ins (managed .NET assemblies created with tools like Visual Studio) and Native plug-ins (platform-specific native code libraries). More info
See in Glossary
to work with the new UnityFramework and the updated Xcode project structure. This migration involves updating API calls, handling lifecycle events differently, and ensuring your plug-ins are correctly configured in the Unity Editor.

Configure plug-in compatibility

Ensure your plug-in is set to be included in the correct Xcode project type. By default, plug-ins are included in both the Objective-C and Swift project types. In the Unity Editor, open the Plugin InspectorA Unity window that displays information about the currently selected GameObject, asset or project settings, allowing you to inspect and edit the values. More info
See in Glossary
for your native plug-inA platform-specific native code library that is created outside of Unity for use in Unity. Allows you can access features like OS calls and third-party code libraries that would otherwise not be available to Unity. More info
See in Glossary
and review its platform settings to confirm the correct compatibility. For more information, refer to Configure a plug-in for iOS with the Inspector window.

Adapt to UnityFramework API changes

The contents of UnityFramework are different when using a Swift Xcode project type. Review your plug-in’s dependencies and update any code that relies on functions or classes that are no longer available.

The UnityPlayer class now provides most of the functionality previously available through UnityAppController.

Note: UnityPlayer isn’t a direct substitute, so it’s recommended to review the Swift project type API reference for details on its specific methods and properties.

// Before:
UnityAppController* appController = GetAppController();

// After (Swift):
let player = UnityPlayer.shared

// After (Objective-C):
UnityPlayer *player = [UnityPlayer shared];

View and ViewController Access

To access the main rendering view and root view controller, use the properties on the UnityPlayer instance.

// Before:
UIView* unityView = GetAppController().unityView;
UIView* unityView = UnityGetUnityView();
UIViewController* rootVC = GetAppController().rootViewController;
UIViewController* rootVC = UnityGetGLViewController();

// After (Swift):
let unityView = UnityPlayer.shared.renderingView
let rootVC = UnityPlayer.shared.rootViewController

// After (Objective-C):
UIView *unityView = [[UnityPlayer shared] renderingView];
UIViewController *rootVC = [[UnityPlayer shared] rootViewController];

Pause and Resume

Pausing and resuming the application is now handled through methods on the UnityPlayer instance. For example:

// Before:
if (!UnityIsPaused()) {
    UnityPause(1);  // pause
}
UnityPause(0);  // resume

// After (Swift):
if (!UnityPlayer.shared.isPaused()) {
    UnityPlayer.shared.pause()
}
UnityPlayer.shared.resume()

// After (Objective-C):
if (![[UnityPlayer shared] isPaused]) {
    [[UnityPlayer shared] pause];
}
[[UnityPlayer shared] resume];

Migrate to NotificationCenter for lifecycle events

If your plug-in previously depended on LifeCycleListener.h or AppDelegateListener, you must migrate to using NotificationCenter to handle lifecycle events. The event definitions are now located in UnityFramework/UnityPluginInterface/UnityNotifications.swift.

// Before (using LifeCycleListener protocol):
@interface MyPlugin : NSObject<AppDelegateListener>
@end
- (void)applicationWillFinishLaunchingWithOptions:(NSNotification*)notification { ... }

// After (Swift):
NotificationCenter.default.addObserver(
    forName: UnityNotifications.applicationWillFinishLaunching,
    object: nil, queue: nil
) { _ in /* handle */ }

// After (Objective-C):
[[NSNotificationCenter defaultCenter]
    addObserverForName:UnityNotifications.applicationWillFinishLaunching
    object:nil queue:nil usingBlock:^(NSNotification *note) { /* handle */ }];

Available notifications include:

  • applicationWillFinishLaunching
  • applicationDidRegisterForRemoteNotifications
  • applicationDidFailToRegisterForRemoteNotifications
  • applicationDidReceiveRemoteNotification
  • unityDidQuit
  • unityDidUnload
  • applicationHandleEventsForBackgroundURLSession
  • sceneOpenURLContexts
  • UIApplication.didBecomeActiveNotification
  • UIApplication.didFinishLaunchingNotification

Note: To prevent duplicate notifications, Unity filters out certain lifecycle and app delegate events that iOS already provides, such as didFinishLaunchingNotification.

Call C# from native code

For the Swift project type, the recommended way to call into C# script is by using the UnityPlayer.sendMessage() method. The UnitySendMessage() C function is still available but now requires you to import UnityPluginInterface.h.

// Before (C/C++/Objective-C):
UnitySendMessage("GameObjectName", "MethodName", "argument");

// After (Swift):
UnityPlayer.shared.sendMessage(toGameObject: "GameObjectName", method: "MethodName", argument: "argument")
UnitySendMessage("GameObjectName", "MethodName", "argument")

// After (Objective-C):
#import "UnityPluginInterface.h"
#import <UnityFramework/UnityFramework-Swift.h>

[[UnityPlayer shared] sendMessageToGameObject:@"GameObjectName" method:@"MethodName" argument:@"argument"];
UnitySendMessage("GameObjectName", "MethodName", "argument");

// C/C++ still works (requires #import "UnityPluginInterface.h"):
UnitySendMessage("GameObjectName", "MethodName", "argument");

Conditional Compilation

If you need to support both Xcode project types within the same plug-in source file, use the UNITY_XCODE_PROJECT_TYPE_SWIFT preprocessor macro to create different code paths.

#ifdef UNITY_XCODE_PROJECT_TYPE_SWIFT
    UnityPlayer *player = [UnityPlayer shared];
#else
    UnityAppController* appController = GetAppController();
#endif

Low level native plug-in API

The low-level native plug-in API remains the same, but the location of the header files has changed. The headers are now located in the UnityFramework/UnityPluginInterface/ directory.

However, you can continue to import them in your code using the same syntax as before.

Introduction to the Swift Xcode project type for iOS and tvOS
Structure of a Unity Xcode Swift project type