Migrate your existing Unity iOS project from the Objective-C project type to the new Swift project type.
Consider the following before migrating to a Swift Xcode project type:
Use the following steps to create a Swift Xcode project type:
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.
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.
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
}
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.
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.
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];
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];
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];
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:
applicationWillFinishLaunchingapplicationDidRegisterForRemoteNotificationsapplicationDidFailToRegisterForRemoteNotificationsapplicationDidReceiveRemoteNotificationunityDidQuitunityDidUnloadapplicationHandleEventsForBackgroundURLSessionsceneOpenURLContextsUIApplication.didBecomeActiveNotificationUIApplication.didFinishLaunchingNotificationNote: To prevent duplicate notifications, Unity filters out certain lifecycle and app delegate events that iOS already provides, such as didFinishLaunchingNotification.
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");
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
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.