A simple Unity plug-in for iOS designed to serve as a starting point for creating new plugins that bridge Unity and Swift.
Follow the instructions below to set up the plugin and integrate it into your Unity project.
- Unity 2019.x or later
- Xcode 11 or later
- Clone or download this repository.
- Open the Unity project where you want to integrate the Swift plugin.
- Copy the entire
Assets/Plugins/iOS
folder from this repository into your Unity project'sAssets/Plugins
folder.
Add the following code into Assets/Plugins/iOS/SwiftToUnity/Source/SwiftToUnity.swift
:
import Foundation
@objc public class SwiftToUnity: NSObject {
@objc public static let shared = SwiftToUnity()
/// Returns the "Hello, Swift!" string.
///
/// - Returns: The "Hello, Swift!" string.
@objc public func swiftHelloWorld() -> String {
return "Hello, Swift!"
}
}
Note that here @obc
instructs Swift to make classes or methods available to Objective-C as well as Swift code.
Add the following code into Assets/Plugins/iOS/SwiftToUnity/Source/SwiftToUnityBridge.mm
:
#import <UnityFramework/UnityFramework-Swift.h>
#import "UnityInterface.h"
extern "C"
{
char* cStringCopy(const char* string) {
if (string == NULL) {
return NULL;
}
size_t length = strlen(string) + 1;
char* res = (char*) malloc(length);
if (res != NULL) {
memcpy(res, string, length);
}
return res;
}
char* cHelloWorld()
{
NSString *returnString = [[SwiftToUnity shared] swiftHelloWorld];
return cStringCopy([returnString UTF8String]);
}
}
The SwiftToUnityBridge.mm
file is the bridging medium between Swift and Unity.
Add the following code into Assets/Plugins/iOS/SwiftToUnity/Source/UnityFramework.modulemap
:
framework module UnityFramework {
umbrella header "UnityFramework.h"
export *
module * { export * }
module UnityInterface {
header "UnityInterface.h"
export *
}
}
First, you will need to add the PostProcessing package to your Unity project.
To install the package, go to Window > Package Manager and switch the view from In Project to All. Select Post Processing in the list. In the right panel you'll find information about the package and a button to install or update to the latest available version for the version of Unity you are running.
Now add the following code into Assets/Plugins/iOS/SwiftToUnity/Editor/SwiftToUnityPostProcess.cs
:
#if UNITY_IOS
using System.IO;
using UnityEngine;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditor.iOS.Xcode;
public static class SwiftToUnityPostProcess
{
[PostProcessBuild]
public static void OnPostProcessBuild(BuildTarget buildTarget, string buildPath)
{
Debug.Log("OnPostProcessBuild: " + buildTarget);
if (buildTarget == BuildTarget.iOS)
{
var projectPath = buildPath + "/Unity-iPhone.xcodeproj/project.pbxproj";
var project = new PBXProject();
project.ReadFromFile(projectPath);
var unityFrameworkGuid = project.GetUnityFrameworkTargetGuid();
// Modulemap
project.AddBuildProperty(unityFrameworkGuid, "DEFINES_MODULE", "YES");
var moduleFile = buildPath + "/UnityFramework/UnityFramework.modulemap";
if (!File.Exists(moduleFile))
{
FileUtil.CopyFileOrDirectory("Assets/Plugins/iOS/SwiftToUnity/Source/UnityFramework.modulemap", moduleFile);
project.AddFile(moduleFile, "UnityFramework/UnityFramework.modulemap");
project.AddBuildProperty(unityFrameworkGuid, "MODULEMAP_FILE", "$(SRCROOT)/UnityFramework/UnityFramework.modulemap");
}
// Headers
string unityInterfaceGuid = project.FindFileGuidByProjectPath("Classes/Unity/UnityInterface.h");
project.AddPublicHeaderToBuild(unityFrameworkGuid, unityInterfaceGuid);
string unityForwardDeclsGuid = project.FindFileGuidByProjectPath("Classes/Unity/UnityForwardDecls.h");
project.AddPublicHeaderToBuild(unityFrameworkGuid, unityForwardDeclsGuid);
string unityRenderingGuid = project.FindFileGuidByProjectPath("Classes/Unity/UnityRendering.h");
project.AddPublicHeaderToBuild(unityFrameworkGuid, unityRenderingGuid);
string unitySharedDeclsGuid = project.FindFileGuidByProjectPath("Classes/Unity/UnitySharedDecls.h");
project.AddPublicHeaderToBuild(unityFrameworkGuid, unitySharedDeclsGuid);
// Save project
project.WriteToFile(projectPath);
}
Debug.Log("OnPostProcessBuild: Complete");
}
}
#endif
Be sure to change the following line in SwiftPostProcess.cs
script with the correct path to your UnityFramework.modulemap
file:
FileUtil.CopyFileOrDirectory("Assets/Plugins/iOS/SwiftToUnity/Source/UnityFramework.modulemap", moduleFile);
using System.Runtime.InteropServices;
using UnityEngine;
public class CanvasScript : MonoBehaviour
{
[DllImport("__Internal")]
private static extern string cHelloWorld();
private void Start()
{
cHelloWorld();
}
}
To call Unity methods from Swift, use UnitySendMessage
function like below:
// SwiftToUnity.swift
import Foundation
@objc public class SwiftToUnity: NSObject {
@objc public static let shared = SwiftToUnity()
/// Sends a "Hello World" message to the "Canvas" GameObject by calling the "OnMessageReceived" script method on that object with the "Hello World!" message.
@objc public func swiftSendHelloWorldMessage() {
// The UnitySendMessage function has three parameters: the name of the target GameObject, the script method to call on that object and the message string to pass to the called method.
UnitySendMessage("Canvas", "OnMessageReceived", "Hello World!");
}
}
See SwiftToUnity.swift.
For more information about UnitySendMessage
, check out Unity's Documentation.
This project is licensed under the MIT License.