A "simple" step-by-step tutorial on how to make a bridge between Unity's C# and Xcode's Objective-C. Either way.
- First set up a new scene in Unity and add a plane with a simple sphere above it. So we can interact with it later.
- Make sure the purple
Spherehas aRigidBodyandUse Gravityis enabled.
π‘ You can add some materials to it, so it stands out. And maybe move the
Spherea bit up (on the y-axis).
If you run the scene the purple sphere would drop on the white plane.
Next up we're going to add a GUI button to send information to Objective-c
- Add a
UI -> Button - It should be aligned to the left-bottom
- Rename the button's text to your liking.
- Next stop, create a new C# Script, name it
BehaviourScriptor anything to your liking
Open the script and use this code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Runtime.InteropServices;
public class BehaviourScript : MonoBehaviour {
public GameObject ball;
public Button button;
[DllImport ("__Internal")]
private static extern void calledFromUnity();
void Start () {
button.onClick.AddListener (Tap);
}
void Tap() {
calledFromUnity();
}
void Bounce(string direction) {
ball.GetComponent<Rigidbody>().AddForce(transform.up * 300);
}
}Code blocks explained:
using System.Runtime.InteropServices;Used for external communication.
[DllImport ("__Internal")]
private static extern void calledFromUnity();This creates a reference to the c function calledFromUnity(), which will be implemented in your Xcode project later on.
void Start () {
button.onClick.AddListener (Tap);
}
void Tap() {
calledFromUnity();
}Would listen for a click event on the button. When a click occurs the c-function calledFromUnity() will be called and invoked in (Obj-)C.
void Bounce(string direction) {
ball.GetComponent<Rigidbody>().AddForce(transform.up * 300);
}This would make the ball bounce. Bounce(string) will be called from Obj-c / Xcode.
Now go back into Unity and add the BehaviourScript to your plane and connect Button and GameObject.
At this stage you would have a button which would do nothing (yet) and have a function which isn't called (yet).
- Create a new folder called
Pluginin your project - Create a new folder called
iOSinPlugin - Create a new file called
plugin.mmin thatiOSfolder
β οΈ It's important to add these files to this specific folder. Adding them from Xcode would overwrite theplugin.mmonce you (re)build the Unity project.
plugin.mm should contain the following code:
extern "C" {
void calledFromUnity() {
[[NSNotificationCenter defaultCenter] postNotificationName:@"UnityNotification" object:nil];
}
}This is where the calledFromUnity() function we declared earlier would return. We make the default NSNotificationCenter post a notification with the name "UnityNotification", this way we can intercept it in our own UIViewController later on.
π‘ There are a few options regarding dispatching methods from C to Objective-C's main view, but for now we'll stick to this.
- Open
Build Settings:File -> Build Settingsor pressβ§βB. - Use the following settings:

- Press
Build - Wait ...
- After a while your Xcode project should be created
- Open
Unity-iPhone.xcodeproj
- Create a new Objective-C class in the
Classesfolder nameAppController.
π‘ Make sure you have a
.mmextension for the implementation file and it's linked to theUnity-iPhonetarget.
- Make sure
AppControllerextendsUnityAppController
The two files will look like this:
// .mm
#import "AppController.h"
@implementation AppController {
UIButton *btn;
}
- (void)startUnity:(UIApplication *)application {
[super startUnity:application];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationFired:) name:@"UnityNotification" object:nil];
UIViewController *vc = [UIViewController new];
[vc.view setFrame:self.window.bounds];
[vc.view addSubview:self.rootViewController.view];
[vc addChildViewController:self.rootViewController];
[self.window setRootViewController:vc];
btn = [UIButton buttonWithType:UIButtonTypeSystem];
[btn setTitle:@"To Unity" forState:UIControlStateNormal];
[btn setBackgroundColor:[UIColor whiteColor]];
[btn setTintColor:[UIColor orangeColor]];
[btn setFrame:CGRectMake(10, 10, 100, 50)];
[btn addTarget:self action:@selector(tapButton:) forControlEvents:UIControlEventTouchUpInside];
[vc.view addSubview:btn];
}
- (void)tapButton:(UIButton *)sender {
UnitySendMessage("Plane", "Bounce", "Up");
}
- (void)notificationFired:(NSNotification *)notification {
NSString *originalTitle = [btn titleForState: UIControlStateNormal];
[btn setTitle:@"π" forState:UIControlStateNormal];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[btn setTitle:originalTitle forState:UIControlStateNormal];
});
}
@end
Lets have a look at each code blocks:
@implementation AppController {
UIButton *btn;
}A btn is declared so we can use it among the whole class instance.
- (void)startUnity:(UIApplication *)application {
[super startUnity:application];Since AppController extends UnityAppController and startUnity: is called when the Unity view is loaded, this method will be invoked once the Unity controller is started.
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationFired:) name:@"UnityNotification" object:nil];- (void)notificationFired:(NSNotification *)notification {
NSString *originalTitle = [btn titleForState: UIControlStateNormal];
[btn setTitle:@"π" forState:UIControlStateNormal];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[btn setTitle:originalTitle forState:UIControlStateNormal];
});
}Listen for the "UnityNotification" notification to be fired and call the notificationFired: method.
notificationFired: will change the title of the button and after 1 second set it back to the original one.
UIViewController *vc = [UIViewController new];
[vc.view setFrame:self.window.bounds];
[vc.view addSubview:self.rootViewController.view];
[vc addChildViewController:self.rootViewController];
[self.window setRootViewController:vc];This would create a new UIViewController and places the original unity viewcontroller in it. This way we can add our own UI on top of Unity.
btn = [UIButton buttonWithType:UIButtonTypeSystem];
[btn setTitle:@"To Unity" forState:UIControlStateNormal];
[btn setBackgroundColor:[UIColor whiteColor]];
[btn setTintColor:[UIColor orangeColor]];
[btn setFrame:CGRectMake(10, 10, 100, 50)];
[btn addTarget:self action:@selector(tapButton:) forControlEvents:UIControlEventTouchUpInside];
[vc.view addSubview:btn];Creates the actual button and places it on the newly created UIViewController
- (void)tapButton:(UIButton *)sender {
UnitySendMessage("Plane", "Bounce", "Up");
}The button tap will invoke tapButton: and will fire UnitySendMessage with 3 parameters:
"Plane": The name of theGameObjectin Unity"Bounce": The name of the function in theBehaviourScript.csUnity C# Script."Up": The parameter to be used in theBounce(string)function. (For now this hasn't any effect, you can place any string in it)
- Open
main.mm(also in the Classes folder) and change this line:
const char* AppControllerClassName = "UnityAppController";to
const char* AppControllerClassName = "AppController";This way it will load the AppController class instead of the UnityAppController class.






