{"id":1393,"date":"2022-01-17T11:05:30","date_gmt":"2022-01-17T02:05:30","guid":{"rendered":"http:\/\/yoonhada.com\/?p=1393"},"modified":"2023-12-26T21:30:57","modified_gmt":"2023-12-26T12:30:57","slug":"unity3d-xcode-unityappcontroller-mm-%ed%95%a8%ec%88%98-%ec%9e%ac-%ec%a0%95%ec%9d%98","status":"publish","type":"post","link":"http:\/\/yoonhada.com\/?p=1393","title":{"rendered":"Override app delegate in Unity for iOS and macOS (1\/4)"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><a href=\"http:\/\/blog.eppz.eu\/override-app-delegate-unity-ios-macos-1\/\">http:\/\/blog.eppz.eu\/override-app-delegate-unity-ios-macos-1\/<\/a><\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>workflow<\/li><li>advanced<\/li><li>code design<\/li><li>github<\/li><li>ios<\/li><li>macos<\/li><li>understanding<\/li><li>unity<\/li><li>unity3d<\/li><li>workflow<\/li><li>march 2, 2017<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">When it comes to create native plugins for Unity, often the plugins need&nbsp;<strong>customize behaviour how the application starts \/ launches<\/strong>&nbsp;by override app delegate (see&nbsp;<code><a href=\"https:\/\/developer.apple.com\/reference\/uikit\/uiapplicationdelegate\" target=\"_blank\" rel=\"noreferrer noopener\">UIApplicationDelegate<\/a><\/code>&nbsp;for iOS and&nbsp;<code><a href=\"https:\/\/developer.apple.com\/reference\/appkit\/nsapplicationdelegate\" target=\"_blank\" rel=\"noreferrer noopener\">NSApplicationDelegate<\/a><\/code>&nbsp;for macOS). Opening app via Push Notifications, URL Schemes, Documents, User activities, or even via WatchKit events are all great examples of this.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">TL;DR<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">You may get the example project immediately by heading to GitHub (in that case you should really be aware of the folder structure at the end of the article, as there are numerous sub-projects can be found all around). However, I strongly recommend to take the next 15 minutes to understand what is going on, and read along.<a href=\"https:\/\/github.com\/eppz\/Unity.Blog.Override_App_Delegate\" target=\"_blank\" rel=\"noreferrer noopener\">&nbsp;See&nbsp;<strong>Unity.Blog.Override_App_Delegate<\/strong>&nbsp;at GitHub<\/a><\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Override app delegate in iOS Unity player (Poor man\u2019s method)<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Like many things in the Unity ecosystem, this feature is also heavily underdocumented. However, if you take a closer look to a Unity iOS player&nbsp;<a href=\"https:\/\/developer.apple.com\/xcode\/\" target=\"_blank\" rel=\"noreferrer noopener\">Xcode<\/a>&nbsp;project, you can find that&nbsp;<strong>Unity provided some tools<\/strong>&nbsp;that can help.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">There is an external constant called&nbsp;<strong>AppControllerClassName<\/strong>&nbsp;can be found in every&nbsp;main.mm&nbsp;of every iOS Unity player&nbsp;<a href=\"https:\/\/developer.apple.com\/xcode\/\" target=\"_blank\" rel=\"noreferrer noopener\">Xcode<\/a>&nbsp;project.&nbsp;<strong>This class name will be passed as the app delegate class<\/strong>&nbsp;to&nbsp;<code><a href=\"https:\/\/developer.apple.com\/reference\/uikit\/1622933-uiapplicationmain?language=objc\" target=\"_blank\" rel=\"noreferrer noopener\">UIApplicationMain<\/a><\/code>. That means that&nbsp;<code><a href=\"https:\/\/developer.apple.com\/reference\/uikit\/uiapplication\" target=\"_blank\" rel=\"noreferrer noopener\">UIApplication<\/a><\/code>&nbsp;(or any principal class given in&nbsp;<code><a href=\"https:\/\/developer.apple.com\/library\/content\/documentation\/General\/Reference\/InfoPlistKeyReference\/Introduction\/Introduction.html\" target=\"_blank\" rel=\"noreferrer noopener\">Info.plist<\/a><\/code>) will create an instance of that delegate (that should conform to&nbsp;<code><a href=\"https:\/\/developer.apple.com\/reference\/uikit\/uiapplicationdelegate\" target=\"_blank\" rel=\"noreferrer noopener\">UIApplicationDelegate<\/a><\/code>), and call the given template methods throughout the application lifecycle.<a href=\"http:\/\/eppz.eu\/blog\/wp-content\/uploads\/IMPL_APP_CONTROLLER_SUBCLASS.png\"><\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"caption-attachment-2786\">There you can find the only piece of documentation about this thing in that single comment line.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Unity also provided a macro called&nbsp;<strong>IMPL_APP_CONTROLLER_SUBCLASS(className)<\/strong>&nbsp;that creates a tiny little category, which overrides the&nbsp;<strong>AppControllerClassName<\/strong>&nbsp;constant as soon as it gets loaded (along all the other classes).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In short, if you put this file&nbsp;<code><a href=\"https:\/\/gist.github.com\/eppz\/87096bd70d070f7093fd0234b187facb\" target=\"_blank\" rel=\"noreferrer noopener\">OverrideAppDelegate.m<\/a><\/code>&nbsp;into your&nbsp;Plugins&nbsp;folder, you can essentially extend \/ override app delegate this way.#import &#8220;UnityAppController.h&#8221;@interface OverrideAppDelegate <strong>:<\/strong> UnityAppController@endIMPL_APP_CONTROLLER_SUBCLASS<strong>(<\/strong>OverrideAppDelegate<strong>)<\/strong>@implementation OverrideAppDelegate-<strong>(<\/strong>BOOL<strong>)<\/strong>application:<strong>(<\/strong>UIApplication*<strong>)<\/strong> application didFinishLaunchingWithOptions:<strong>(<\/strong>NSDictionary*<strong>)<\/strong> options<strong>{<\/strong> NSLog<strong>(<\/strong>@&#8221;[OverrideAppDelegate application:%@ didFinishLaunchingWithOptions:%@]&#8221;, application, options<strong>)<\/strong>; return <strong>[<\/strong>super application:application didFinishLaunchingWithOptions:options<strong>]<\/strong>;<strong>}<\/strong>@end<a href=\"https:\/\/gist.github.com\/eppz\/87096bd70d070f7093fd0234b187facb\" target=\"_blank\" rel=\"noreferrer noopener\">&nbsp;See&nbsp;<strong>OverrideAppDelegate.m<\/strong>&nbsp;at GitHub<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This can be a quick solution when your project has&nbsp;<strong>a single iOS plugin<\/strong>&nbsp;intended to override app delegate. But if you are about to use more iOS plugins that uses the same technique,&nbsp;<strong>one or the other will be broken<\/strong>. (Unfortunately) you can find countless Unity plugins on GitHub using the very same technique.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You may create an override chain of plugins, but if you are conflicting with a closed source iOS plugin binary that uses this technique, then you basically can\u2019t (unless you crack it).<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Unity Plugin workflow considerations when override app delegate<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">To have a maintainable plugin, the first consideration is&nbsp;<strong>being totally encapsulated<\/strong>. It should not make a single assumption about the application, also it should not change a single thing in the application architecture itself. In the example above, you&nbsp;<strong>make two assumptions, both can be wrong<\/strong>. You assume that the base class of the app is&nbsp;UnityAppController, then you are assume that the value of&nbsp;AppControllerClassName&nbsp;is not gonna be changed after you have changed so.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So in general, if you make such assumptions, the application may break the plugin (often the case when using multiple plugins), or the plugin may break the app (often the case when the app development progresses, but the plugin does not follow).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I found that the most common consideration people pass over during plugin development is&nbsp;<strong>being compatible with other plugins<\/strong>&nbsp;(!). You may define a new base class for the main Unity controller, but if you are using another plugin that essentially does the same, you will break its intended behaviour.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Almost the same considerations lead to the Unity Android Plugin Architecture in the article&nbsp;<a href=\"http:\/\/eppz.eu\/blog\/unity-android-plugin-tutorial-2\/\" target=\"_blank\" rel=\"noreferrer noopener\"><strong>Unity Android plugin tutorial (2\/3)<\/strong>&nbsp;Project setup and workflow<\/a>, that extends behaviour without overriding application\u2019s main&nbsp;<code><a href=\"http:\/\/developer.android.com\/guide\/components\/activities.html\" target=\"_blank\" rel=\"noreferrer noopener\">Activity<\/a><\/code>. Two or more plugins wanting to do the same could also create such conflicting situations.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ultimately this mindset leads to&nbsp;<strong>a healthier Unity plugin ecosystem<\/strong>&nbsp;in the long run.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Unity Plugin architectures for iOS and macOS<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>On iOS<\/strong>, Unity plugins can be packed \/ compiled along with the rest of the application code. They can be added in form of native classes, static or dynamic libraries (Libraries or Frameworks using iOS terms). That means native&nbsp;<strong>plugin classes gets loaded alongside the application classes<\/strong>. As application launch happens after the classes gets loaded, iOS plugins can extend application launching behaviours more easily.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>On macOS<\/strong>, however, Unity asks for plugins in form of bundles (following the general macOS plugin pattern). That means that plugin code will be loaded by the Objective-C application runtime (probably using an :[NSBunde load]: call). As a consequence,&nbsp;<strong>the plugin code gets loaded after the application has finished launching<\/strong>, seemingly even after Unity Player has launched, around the loading of the first scene. Obviously, using solely this architecture, you cannot customize app launching behaviour with macOS plugins.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">A simple yet maintainable Unity iOS plugin workflow<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Now comes the step-by-step tutorial part. First we create a simple Unity iOS plugin. While you can add Objective-C sources directly to Unity, I find it more maintainable to&nbsp;<strong>pack plugins as libraries<\/strong>&nbsp;(or even frameworks).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In general, I found it really convenient to&nbsp;<strong>have the native plugin projects<\/strong>&nbsp;(iOS, macOS, Android)&nbsp;<strong>in the Unity project root folder<\/strong>&nbsp;(outside&nbsp;Assets&nbsp;folder), then setup a copy command in&nbsp;<a href=\"https:\/\/developer.apple.com\/xcode\/\" target=\"_blank\" rel=\"noreferrer noopener\">Xcode<\/a>&nbsp;that puts the resulting plugins into Assets folder (I actually did something very similar at&nbsp;<a href=\"http:\/\/eppz.eu\/blog\/unity-android-plugin-tutorial-2\/\" target=\"_blank\" rel=\"noreferrer noopener\"><strong>Unity Android plugin tutorial (2\/3)<\/strong>&nbsp;Project setup and workflow<\/a>). Having this, version control also comes really easy (you can even maintain sub-projects as&nbsp;<a href=\"https:\/\/git-scm.com\/book\/en\/v2\/Git-Tools-Submodules\" target=\"_blank\" rel=\"noreferrer noopener\">Git Submodules<\/a>).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So for this plugin, you should make a&nbsp;<strong>folder called&nbsp;iOS&nbsp;beside the&nbsp;Assets&nbsp;folder<\/strong>. As your native platform count grows, this folder structure can really grow with them.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"http:\/\/eppz.eu\/blog\/wp-content\/uploads\/Create_Cocoa_Touch_Static_Library.png\" alt=\"Create Cocoa Touch Static Library\" class=\"wp-image-2255\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"http:\/\/eppz.eu\/blog\/wp-content\/uploads\/Create_Override_iOS_Static_Library.png\" alt=\"Create Override iOS Static Library\" class=\"wp-image-2256\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Now in&nbsp;<a href=\"https:\/\/developer.apple.com\/xcode\/\" target=\"_blank\" rel=\"noreferrer noopener\">Xcode<\/a>&nbsp;create a new&nbsp;<a href=\"https:\/\/en.wikipedia.org\/wiki\/Static_library\" target=\"_blank\" rel=\"noreferrer noopener\"><strong>Cocoa Touch Static Library<\/strong><\/a>&nbsp;called&nbsp;Override_iOS. It automatically creates a single class called&nbsp;<code><a href=\"https:\/\/github.com\/eppz\/Unity.Blog.Override_App_Delegate\/blob\/master\/iOS\/Override_iOS\/Override_iOS\/Override_iOS.h\" target=\"_blank\" rel=\"noreferrer noopener\">Override_iOS<\/a><\/code>. To see the plugin working, we simply&nbsp;<strong>log a message to the console when it is loaded<\/strong>. Fortunately Objective-C classes have a class method template called&nbsp;<code><a href=\"https:\/\/developer.apple.com\/reference\/objectivec\/nsobject\/1418815-load?language=objc\" target=\"_blank\" rel=\"noreferrer noopener\">load<\/a><\/code>&nbsp;you can use for this.#import &#8220;Override_iOS.h&#8221;@implementation Override_iOS+<strong>(<\/strong>void<strong>)<\/strong>load<strong>{<\/strong> NSLog<strong>(<\/strong>@&#8221;[Override_iOS load]&#8221;<strong>)<\/strong>; <strong>}<\/strong>@end<a href=\"https:\/\/github.com\/eppz\/Unity.Blog.Override_App_Delegate\/blob\/1\/iOS\/Override_iOS\/Override_iOS\/Override_iOS.m\" target=\"_blank\" rel=\"noreferrer noopener\">&nbsp;See&nbsp;<strong>Override_iOS.m<\/strong>&nbsp;at GitHub<\/a><\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><a href=\"http:\/\/eppz.eu\/blog\/wp-content\/uploads\/New_Copy_Files_Build_Phase.png\"><img decoding=\"async\" src=\"http:\/\/eppz.eu\/blog\/wp-content\/uploads\/New_Copy_Files_Build_Phase.png\" alt=\"New Copy Files Build Phase\" class=\"wp-image-2763\"\/><\/a><\/figure><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">You can build the library&nbsp;\u2318+B, the resulting file&nbsp;libOverride_iOS.a&nbsp;can be found in the&nbsp;<em>Products<\/em>&nbsp;group. Next we&nbsp;<strong>make&nbsp;<a href=\"https:\/\/developer.apple.com\/xcode\/\" target=\"_blank\" rel=\"noreferrer noopener\">Xcode<\/a>&nbsp;to deploy the library file automatically<\/strong>. First make sure you have a folder called&nbsp;Plugins&nbsp;in Unity. After that, select the&nbsp;<em>Override_iOS<\/em>&nbsp;target in&nbsp;<a href=\"https:\/\/developer.apple.com\/xcode\/\" target=\"_blank\" rel=\"noreferrer noopener\">Xcode<\/a>, and add a&nbsp;<em>New Copy Files Phase<\/em>&nbsp;in the targets&nbsp;<em>Build Phases<\/em>.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><a href=\"http:\/\/eppz.eu\/blog\/wp-content\/uploads\/Copy_Files_Build_Phase_Absolute_Path.png\"><img decoding=\"async\" src=\"http:\/\/eppz.eu\/blog\/wp-content\/uploads\/Copy_Files_Build_Phase_Absolute_Path.png\" alt=\"Copy Files Build Phase Absolute Path\" class=\"wp-image-2764\"\/><\/a><\/figure><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Drag the&nbsp;libOverride_iOS.a&nbsp;to the file list, then simply define the&nbsp;Assets\/Plugins&nbsp;folder as an&nbsp;<em>Absolute Path<\/em>&nbsp;(you can see where my project resides above, you should locate yours). After hit build&nbsp;\u2318+B&nbsp;in&nbsp;<a href=\"https:\/\/developer.apple.com\/xcode\/\" target=\"_blank\" rel=\"noreferrer noopener\">Xcode<\/a>, the library should be copied right into your Unity project.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"http:\/\/eppz.eu\/blog\/wp-content\/uploads\/iOS_Static_Library_Unity_Import_Setting.png\" alt=\"iOS Static Library Unity Import Setting\" class=\"wp-image-2255\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"http:\/\/eppz.eu\/blog\/wp-content\/uploads\/iOS_Unity_PlayerSettings.png\" alt=\"iOS Unity PlayerSettings\" class=\"wp-image-2256\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">If you click on the&nbsp;libOverride_iOS.a&nbsp;file in Unity project window, you can see the Unity plugin inspector. Select&nbsp;<strong>iOS as the plugin platform<\/strong>, and click apply. Similar to the structure I used with plugin projects, I prefer somewhat similar folder structure for Unity builds as well. So make a folder called&nbsp;Build&nbsp;beside&nbsp;Assets, then create an&nbsp;iOS&nbsp;folder in it. To be able to run the app in the simulator,&nbsp;<strong>set&nbsp;<em>Target SDK<\/em>&nbsp;to&nbsp;<em>Simulator SDK<\/em><\/strong>&nbsp;in&nbsp;<em>iOS PlayerSettings<\/em>.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"http:\/\/eppz.eu\/blog\/wp-content\/uploads\/Unity_iOS_Player_Plugin_Static_Library.png\" alt=\"Unity iOS Player Plugin Static Library\" class=\"wp-image-2255\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"http:\/\/eppz.eu\/blog\/wp-content\/uploads\/Unity_iOS_Player_Build_Phases_Link_Binary_With_Libraries.png\" alt=\"Unity iOS Player Build Phases Link Binary With Libraries\" class=\"wp-image-2256\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">There you go, build an iOS player, then open it in&nbsp;<a href=\"https:\/\/developer.apple.com\/xcode\/\" target=\"_blank\" rel=\"noreferrer noopener\">Xcode<\/a>. You can see that the&nbsp;<strong>library has been deployed<\/strong>&nbsp;to the&nbsp;Libraries\/Plugins&nbsp;group, also if you take a look on the&nbsp;<em>Build Phases<\/em>&nbsp;tab, it is linked in the&nbsp;<em>Link Binary With Libraries<\/em>&nbsp;along with the rest of the libraries.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Load iOS Unity plugin before application launches<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Now if you run&nbsp;\u2318+R&nbsp;the resulting iOS app in the simulator, you should see the message coming from the plugin in the console indicating that the framework has been loaded. But you don\u2019t.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"http:\/\/eppz.eu\/blog\/wp-content\/uploads\/Unity_iOS_Build_Target.png\" alt=\"Unity iOS Build Target\" class=\"wp-image-2255\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"http:\/\/eppz.eu\/blog\/wp-content\/uploads\/Unity_iOS_Build_Other_Linker_Flags_ObjC.png\" alt=\"Unity iOS Build Other Linker Flags ObjC\" class=\"wp-image-2256\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">You don\u2019t see it, as by default iOS won\u2019t link the library until you need it. You can change this behaviour by&nbsp;<strong>tell the linker to force load static library symbols<\/strong>. Select the&nbsp;Unity-iPhone&nbsp;build target in&nbsp;<a href=\"https:\/\/developer.apple.com\/xcode\/\" target=\"_blank\" rel=\"noreferrer noopener\">Xcode<\/a>, then in the Build Settings tab, add this entry to the&nbsp;<em>Other Linker Flags<\/em>&nbsp;<code><a href=\"https:\/\/developer.apple.com\/library\/content\/qa\/qa1490\/_index.html\" target=\"_blank\" rel=\"noreferrer noopener\">-ObjC<\/a><\/code>.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><a href=\"http:\/\/eppz.eu\/blog\/wp-content\/uploads\/Unity_iOS_Player_Console_Log.png\"><img decoding=\"async\" src=\"http:\/\/eppz.eu\/blog\/wp-content\/uploads\/Unity_iOS_Player_Console_Log.png\" alt=\"Unity iOS Build Other Linker Flags ObjC\" class=\"wp-image-2778\"\/><\/a><\/figure><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">After this, run&nbsp;\u2318+R&nbsp;the resulting iOS app in the simulator, and take a look at the console. You can see&nbsp;[Override_iOS load]&nbsp;right at the top, that means&nbsp;<strong>the plugin code has been loaded before&nbsp;<\/strong>(!)<strong>&nbsp;any other thing happened<\/strong>&nbsp;in the application. This is very promising considering that we want to override app launching behaviour later on.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To manage the workflow accordingly, the build settings alteration should be included right into the Unity project. There is an API called&nbsp;<code><a href=\"https:\/\/docs.unity3d.com\/ScriptReference\/iOS.Xcode.PBXProject.html\" target=\"_blank\" rel=\"noreferrer noopener\">PBXProject<\/a><\/code>&nbsp;to&nbsp;<strong>manipulate the built&nbsp;<a href=\"https:\/\/developer.apple.com\/xcode\/\" target=\"_blank\" rel=\"noreferrer noopener\">Xcode<\/a>&nbsp;project<\/strong>. So create a file in Unity called&nbsp;<code><a href=\"https:\/\/gist.github.com\/eppz\/1ebbc1cf6a77741f56d63d3803e57ba3\" target=\"_blank\" rel=\"noreferrer noopener\">BuildPostProcessor.cs<\/a><\/code>&nbsp;in&nbsp;Assets\/Editor, and put this content from the Gist below (you can remove the frameworks part leaving the linker flag only). This method also proven quiet useful when hijacking macOS executables later.https:\/\/platform.twitter.com\/embed\/Tweet.html?dnt=false&amp;embedId=twitter-widget-2&amp;features=eyJ0ZndfZXhwZXJpbWVudHNfY29va2llX2V4cGlyYXRpb24iOnsiYnVja2V0IjoxMjA5NjAwLCJ2ZXJzaW9uIjpudWxsfSwidGZ3X2hvcml6b25fdHdlZXRfZW1iZWRfOTU1NSI6eyJidWNrZXQiOiJodGUiLCJ2ZXJzaW9uIjpudWxsfSwidGZ3X3NwYWNlX2NhcmQiOnsiYnVja2V0Ijoib2ZmIiwidmVyc2lvbiI6bnVsbH19&amp;frame=false&amp;hideCard=false&amp;hideThread=false&amp;id=821489274692444160&amp;lang=en&amp;origin=http%3A%2F%2Fblog.eppz.eu%2Foverride-app-delegate-unity-ios-macos-1%2F&amp;sessionId=4998a53c135c3b6deb85bfe528b8e68ec5bf17bd&amp;theme=light&amp;widgetsVersion=86e9194f%3A1641882287124&amp;width=550px<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Implement basic features in Unity iOS plugin<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Ready to add some basic features to the plugin, actually&nbsp;<strong>a simple hello world<\/strong>&nbsp;that comes to Unity from the plugin side. So create some files in the plugin&nbsp;<a href=\"https:\/\/developer.apple.com\/xcode\/\" target=\"_blank\" rel=\"noreferrer noopener\">Xcode<\/a>&nbsp;project. A helper tool called&nbsp;<code><a href=\"https:\/\/github.com\/eppz\/Unity.Blog.Override_App_Delegate\/blob\/master\/iOS\/Override_iOS\/Override_iOS\/UnityString_C%2B%2B.mm\" target=\"_blank\" rel=\"noreferrer noopener\">UnityString_C++.mm<\/a><\/code>&nbsp;for string conversion between iOS and Unity, and a simple Objective-C++ file called&nbsp;<code><a href=\"https:\/\/github.com\/eppz\/Unity.Blog.Override_App_Delegate\/blob\/master\/iOS\/Override_iOS\/Override_iOS\/Override_C%2B%2B.mm\" target=\"_blank\" rel=\"noreferrer noopener\">Override_C++.mm<\/a><\/code>&nbsp;with a single static external C function called&nbsp;<code><a href=\"https:\/\/github.com\/eppz\/Unity.Blog.Override_App_Delegate\/blob\/1\/iOS\/Override_iOS\/Override_iOS\/Override_C%2B%2B.mm#L22\" target=\"_blank\" rel=\"noreferrer noopener\">getMessage<\/a><\/code>.#import &#8220;UnityString_C++.mm&#8221;#import &#8220;Override_iOS.h&#8221;extern &#8220;C&#8221;<strong>{<\/strong> const char* getMessage<strong>()<\/strong><strong>{<\/strong> return UnityStringFromNSString<strong>(<\/strong>@&#8221;Greetings from iOS!&#8221;<strong>)<\/strong>; <strong>}<\/strong><strong>}<\/strong><a href=\"https:\/\/github.com\/eppz\/Unity.Blog.Override_App_Delegate\/blob\/1\/iOS\/Override_iOS\/Override_iOS\/Override_C%2B%2B.mm\" target=\"_blank\" rel=\"noreferrer noopener\">&nbsp;See&nbsp;<strong>Override_C++.mm<\/strong>&nbsp;at GitHub<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">After this you can now create the&nbsp;<strong>C# counterpart<\/strong>&nbsp;in Unity. Create a C# script file called&nbsp;<code><a href=\"https:\/\/github.com\/eppz\/Unity.Blog.Override_App_Delegate\/blob\/1\/Assets\/Plugins\/Override.cs\" target=\"_blank\" rel=\"noreferrer noopener\">Override.cs<\/a><\/code>&nbsp;in&nbsp;Assets\/Plugins&nbsp;folder, then hook up the message from the plugin with a text label. These parts are mostly taken after the official&nbsp;<a href=\"https:\/\/docs.unity3d.com\/Manual\/PluginsForIOS.html\" target=\"_blank\" rel=\"noreferrer noopener\">Building Plugins for iOS<\/a>&nbsp;documentation.using UnityEngine;using UnityEngine.UI;using System.Runtime.InteropServices;public class Override <strong>:<\/strong> MonoBehaviour<strong>{<\/strong> public Text label;#if !UNITY_EDITOR &amp;&amp; UNITY_IOS <strong>[<\/strong>DllImport<strong>(<\/strong>&#8220;__Internal&#8221;<strong>)]<\/strong> static extern string getMessage<strong>()<\/strong>; void Awake<strong>()<\/strong><strong>{<\/strong> label.text = getMessage<strong>()<\/strong>; <strong>}<\/strong>#endif<strong>}<\/strong><a href=\"https:\/\/github.com\/eppz\/Unity.Blog.Override_App_Delegate\/blob\/1\/Assets\/Plugins\/Override.cs\" target=\"_blank\" rel=\"noreferrer noopener\">&nbsp;See&nbsp;<strong>Override.cs<\/strong>&nbsp;at GitHub<\/a><\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"http:\/\/eppz.eu\/blog\/wp-content\/uploads\/Unity_iOS_Plugin_Workflow_Folder_Structure.png\" alt=\"Unity iOS Plugin Workflow Folder Structure\" class=\"wp-image-2255\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"http:\/\/eppz.eu\/blog\/wp-content\/uploads\/Unity_iOS_Plugin_Hello_World_400px.png\" alt=\"Unity iOS Plugin Hello World 400px\" class=\"wp-image-2256\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">There you go, you have setup&nbsp;<strong>a really convenient plugin workflow<\/strong>&nbsp;that fits well to version control, changes, also come without any need for manual&nbsp;<a href=\"https:\/\/developer.apple.com\/xcode\/\" target=\"_blank\" rel=\"noreferrer noopener\">Xcode<\/a>&nbsp;project post-processing (you can recap the resulting folder structure to the left).&nbsp;<strong>Ready to be filled up<\/strong>&nbsp;with all the heavy features in the upcoming parts of the series.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>http:\/\/blog.eppz.eu\/override-app-delegate-unity-ios-macos-1\/ workflow advanced code design github ios macos understanding unity unity3d workflow march 2, 2017 When it comes to create native plugins for Unity, often the plugins need&nbsp;customize behaviour how the application starts \/ launches&nbsp;by override app delegate (see&nbsp;UIApplicationDelegate&nbsp;for iOS and&nbsp;NSApplicationDelegate&nbsp;for macOS). Opening app via Push Notifications, URL Schemes, Documents, User activities, or even via [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[83],"tags":[42],"class_list":["post-1393","post","type-post","status-publish","format-standard","hentry","category-archive","tag-unity"],"_links":{"self":[{"href":"http:\/\/yoonhada.com\/index.php?rest_route=\/wp\/v2\/posts\/1393","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/yoonhada.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/yoonhada.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/yoonhada.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/yoonhada.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1393"}],"version-history":[{"count":2,"href":"http:\/\/yoonhada.com\/index.php?rest_route=\/wp\/v2\/posts\/1393\/revisions"}],"predecessor-version":[{"id":1397,"href":"http:\/\/yoonhada.com\/index.php?rest_route=\/wp\/v2\/posts\/1393\/revisions\/1397"}],"wp:attachment":[{"href":"http:\/\/yoonhada.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1393"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/yoonhada.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1393"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/yoonhada.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1393"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}