Home / Tutorial / iOS Camera Plugin for Unity: COMPLETE Tutorial

iOS Camera Plugin for Unity: COMPLETE Tutorial

/
/
/
883 Views

Following the previous tutorial on how to create an Android Camera Plugin, I’ve decided to create a similar one – an iOS Camera Plugin for Unity.

XCODE PROJECT

  • Create a new Xcode Project and choose the Single View Application template; IMAGE1, IMAGE2
  • Add a new Target and choose the Cocoa Touch Static Library template; IMAGE3, IMAGE4, IMAGE5

The Library will be the one imported into Unity and we will use the Application Target to create a very simple native app to test the plugin.

IMO the Unity building process for iOS is slower than for Android. So when developing my own plugin, I’ve decided to implement a native application for testing the plugin before exporting it.


NATIVE MEDIA

IMPLEMENT THE IOS CAMERA

The plugin is called Native Media because, since they are so similar, we will implement the Camera and Gallery access on the same library.

Just like in Android, we will implement the native methods and use the UnitySendMessage (GameObject, Method, String) to return values into Unity.

  • Add the methods selectPicture and takePicture to the NativeMedia.h (interface file) and NativeMedia.m (implementation file);
  • The only difference between the Camera and the Gallery access is the media type, so add a new method called newPicture to the NativeMedia.m file with an additional parameter of type UIImagePickerControllerSourceType;

It is also possible to write just one method with the source type and call it from Unity. But, I prefer it this way.  In Unity, we don’t have to “know” about the picker source type.

  • To access the UIImagePickerControllerSourceType you need to import the UIKit.h on the NativeMedia.h;
  • Call the newPicture method from both the selectPicture and the takePicture methods and pass the correct source type;
  • We should also check if the device has a camera before trying to access it and warn the user if it’s not possible;
  • Since we’ll need to use the filenamecallback and gameObject to send the data back into Unity, let’s create some instance variables to store it;
  • Instantiate a UIImagePickerController to access the Camera/Gallery;
  • Set the correct source type;
  • Assign a delegate to receive the result from the Camera/Gallery. To become a valid delegate the class needs to implement the UIImagePickerControllerDelegate – add it to the NativeMedia.h;

First, I tried to assign the delegate to self but it seemed that the instance was going out of scope and the delegate methods were not being called. So I’m using an instance variable to hold the reference while we need it. Not sure if its the best/correct way. I would appreciate any input on this topic 🙂

  • To show the image picker we need to access the Unity View Controller using the UnityGetGLViewController method (change the NativeMedia.m file to an Objective-C++ Source file – NativeMedia.mm) and declare it on the NativeMedia.h; IMAGE7
  • Show the image picker and implement the delegate method in order to receive the result;

SEND THE RESULT TO UNITY

  • We just saved the new/selected image to disk using the chosen filename;
  • Now, let’s send the image path into Unity using the UnitySendMessage method – we also need to declare this method in the NativeMedia.h file;

In order to send an NSString into Unity, we need to convert it into a c string using cStringUsingEncoding and NSUTF8StringEncoding.


IMPLEMENT THE UNITY C LINK METHODS

  • To finish let’s declare the functions that Unity will actually call;

In the same way, in order to send a c string into Objective-C, we need to convert it into an NSString using stringWithUTF8String.

  • Select the NativeMedia target build scheme and the Generic iOS Device; IMAGE8
  • Press Play to build the plugin file – libNativeMedia.a; IMAGE9 IMAGE10 IMAGE11

UNITY PROJECT

CREATE THE UNITY PROJECT

I’m using the same project from the previous Android Camera Plugin for Unity Tutorial. If you completed that one, skip the unnecessary steps.
  • Create a new Unity Project;
  • Import this Unity Package into the project and open the main_initial.scene;
  • Duplicate the button and change the text to Select from Gallery; IMAGE12
This is a very simple scene with a Button to open the camera and an Image component to show the captured image.
  • Switch to the iOS Platform on the project Build Settings and add the current scene; IMAGE13
  • Change the project Bundle Identifier and choose Build and Run. IMAGE14 IMAGE15
This is just to make sure that you can compile the iOS Project before continuing with the tutorial.

ADD THE IOS CAMERA C-SHARP COMPONENT

  • Create a new C-Sharp Script called MediaIOS.cs to communicate with the iOS plugin; IMAGE16
  • Add the following code to call the _SelectPicture and the _TakePicture methods on the iOS Plugin and to receive the result on the PictureCallback method on Unity;
  • Add the MediaIOS.cs component to the Controller GameObject. IMAGE17

IMPLEMENT THE UNITY CONTROLLER COMPONENT

  • Create a new Controller.cs component; IMAGE18
  • Add the following code to the Controller.cs (check the code comments for deeper explanation);
Since I’m using the same project from the last tutorial, I left the Android code on this file. You can always remove it.
  • Assign the Controller.cs serialised references; IMAGE19
  • Link the UI buttons to the Controller.cs component; IMAGE20 IMAGE21

IMPORT THE PLUGIN INTO UNITY

  • Locate the iOS library file – libNativeMedia.a; IMAGE22 IMAGE23
  • Import the file into the Unity and place it inside Assets/Plugins/iOS; IMAGE24

The plugin file is located inside the Libraries/Plugins/iOS. IMAGE25


RUN THE IOS APP

  • Build the Unity Project;
  • Add the following keys to the .plist file to have access to the camera and gallery data: IMAGE26
    • Privacy – Camera Usage Description;
    • Privacy – Photo Library Usage Description;

OPTIONAL: NATIVE APP

Let’s use the Application Target to create a very simple native app to test the plugin.

  • Open the Main.storyboard and add two buttons, one for the camera and one for the gallery; IMAGE27 IMAGE28
  • Link the buttons to two new methods on the ViewController.m (check here on how to do it); IMAGE29 IMAGE30 IMAGE31
  • Import the NativeMedia.h into the ViewController.m and call the plugin methods;
  •  Add the libNativeMedia.a to the app Build Phases; IMAGE32
  • Add the following keys to the .plist file to have access to the camera and gallery data: IMAGE33
    • Privacy – Camera Usage Description;
    • Privacy – Photo Library Usage Description;
  • Change the ViewController.m type to Objective-C++ Source and implement a custom implementation of the UnitySendMessage and the UnityGetGLViewController; IMAGE34
  • Run the app on the iOS Simulator or on a real device; IMAGE35

You won’t be able to test the camera on the simulator.

Result

2017-04-02 01:24:04.016 UnityNativePlugin[23150:321457] Image Selected: /Users/tomazsaraiva/Library/Developer/CoreSimulator/Devices/C3A6DA0F-D4CF-422A-8EC9-73F88CCD4F83/data/Containers/Data/Application/2334EF39-05FD-49E9-8A07-D9FB3FE982CC/Documents/picture.png

I’m not very fluent on Objective-C and iOS development so any corrections, suggestions and tips are welcome. Thanks.

Happy Coding 🙂

Leave a Comment

Your email address will not be published. Required fields are marked *