├── AppDelegate.h ├── AppDelegate.mm ├── README.md ├── UnityIntegration.xcconfig └── imgs ├── 10.png ├── 1_1.png ├── 1_2.png ├── 2.png ├── 3.png ├── 4_1.png ├── 4_2.png ├── 5_1.png ├── 5_2.png ├── 6.png ├── 7.png └── 8.png /AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // UnityIntegration 4 | // 5 | // Created by Volodya Karpliuk on 5/24/16. 6 | // Copyright © 2016 Volodya Karpliuk. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "UnityAppController.h" 11 | 12 | @interface AppDelegate : UIResponder 13 | 14 | @property (strong, nonatomic) UIWindow *window; 15 | @property (strong, nonatomic) UIWindow *unityWindow; 16 | 17 | @property (strong, nonatomic) UnityAppController *unityController; 18 | 19 | - (void)showUnityWindow; 20 | - (void)hideUnityWindow; 21 | 22 | - (void)shouldAttachRenderDelegate; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /AppDelegate.mm: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // UnityIntegration 4 | // 5 | // Created by Volodya Karpliuk on 5/24/16. 6 | // Copyright © 2016 Volodya Karpliuk. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "ViewController.h" 11 | #import "VuforiaRenderDelegate.h" 12 | 13 | @interface AppDelegate () 14 | 15 | @property (nonatomic, strong) UINavigationController *navVC; 16 | 17 | @end 18 | 19 | 20 | extern "C" void VuforiaRenderEvent(int marker); 21 | @implementation AppDelegate 22 | 23 | - (UIWindow *)unityWindow { 24 | return UnityGetMainWindow(); 25 | } 26 | 27 | - (void)showUnityWindow { 28 | [self.unityWindow makeKeyAndVisible]; 29 | 30 | UIButton *back = [UIButton buttonWithType:UIButtonTypeSystem]; 31 | back.backgroundColor = [UIColor yellowColor]; 32 | [back setTitle:@"BACK" forState:UIControlStateNormal]; 33 | back.frame = CGRectMake(0, 0, 100, 44); 34 | back.center = self.unityWindow.center; 35 | 36 | [self.unityWindow addSubview:back]; 37 | 38 | [back addTarget:self action:@selector(hideUnityWindow) forControlEvents:UIControlEventTouchUpInside]; 39 | 40 | 41 | } 42 | 43 | - (void)hideUnityWindow { 44 | [self.window makeKeyAndVisible]; 45 | } 46 | 47 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 48 | 49 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 50 | self.window.backgroundColor = [UIColor redColor]; 51 | 52 | ViewController *viewController = [[ViewController alloc] initWithNibName:nil bundle:nil]; 53 | 54 | self.navVC = [[UINavigationController alloc] initWithRootViewController:viewController]; 55 | self.window.rootViewController = self.navVC; 56 | 57 | self.unityController = [[UnityAppController alloc] init]; 58 | [self.unityController application:application didFinishLaunchingWithOptions:launchOptions]; 59 | 60 | 61 | [self.window makeKeyAndVisible]; 62 | 63 | return YES; 64 | } 65 | 66 | - (void)shouldAttachRenderDelegate { 67 | 68 | self.unityController.renderDelegate = [[VuforiaRenderDelegate alloc] init]; 69 | 70 | UnityRegisterRenderingPlugin(NULL, &VuforiaRenderEvent); 71 | 72 | #if UNITY_VERSION>434 73 | 74 | UnityRegisterRenderingPlugin(NULL, &VuforiaRenderEvent); 75 | 76 | #endif 77 | 78 | } 79 | 80 | - (void)applicationWillResignActive:(UIApplication *)application { 81 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 82 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 83 | [self.unityController applicationWillResignActive:application]; 84 | } 85 | 86 | - (void)applicationDidEnterBackground:(UIApplication *)application { 87 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 88 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 89 | [self.unityController applicationDidEnterBackground:application]; 90 | } 91 | 92 | - (void)applicationWillEnterForeground:(UIApplication *)application { 93 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 94 | [self.unityController applicationWillEnterForeground:application]; 95 | } 96 | 97 | - (void)applicationDidBecomeActive:(UIApplication *)application { 98 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 99 | [self.unityController applicationDidBecomeActive:application]; 100 | } 101 | 102 | - (void)applicationWillTerminate:(UIApplication *)application { 103 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 104 | [self.unityController applicationWillTerminate:application]; 105 | } 106 | 107 | @end 108 | 109 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # iOSUnityVuforiaGuide 2 | Integration of Unity 5.3 + Vuforia 5.5.9 project with native iOS application (Xcode 7.3) 3 | 4 | Inspired by [the-nerd.be](https://the-nerd.be/) tutorials, by Frederik Jacques. 5 | 6 | Let's assume that you already have a Unity project which uses Vuforia SDK. 7 | 8 | In project's Player Settings be sure that you use: 9 | * Scripting Backend - IL2CPP 10 | * Uncheck 'Auto Graphics API' and use only OpenGLES2, because for iOS 9+ Unity tries to use Metal and you can face some issues with that (in my case there were no texture on 3d object) 11 | 12 | Add scene to build and generate iOS project from Unity project and after this step you can close Unity. 13 | 14 | ##Step 1 15 | Create Xcode project and add `UnityIntegration.xcconfig` which you can find in this repo. 16 | 17 | As soon as we need to use files from previously Unity-generated iOS project, you can put the projects together in a common directory. Do not delete project generated with Unity even after all steps done. 18 | 19 | Select project's settings and choose `UnityIntegration.xcconfig` file to be used by your project: 20 | 21 | ![](imgs/1_1.png?raw=true "") 22 | 23 | Now choose `Target -> Build Settings`, scroll down to the end of the list and change values of 24 | `UNITY_IOS_EXPORTED_PATH` and `UNITY_RUNTIME_VERSION` to path of Unity-generated iOS project and version of Unity you use accordingly. 25 | 26 | ![](imgs/1_2.png?raw=true "") 27 | 28 | ##Step 2 29 | Remove `Main.storyboard` from Xcode project. 30 | Also, in `Info.plist` remove `Main storyboard file base name` row: 31 | 32 | ![](imgs/2.png?raw=true "") 33 | 34 | ##Step 3 35 | Create new group, let's call it `"Integration"`. 36 | 37 | Drag and drop inside this group `Classes` and `Libraries` folders from previously Unity-generated iOS project. 38 | 39 | Make sure, that: 40 | * `Copy resources if needed` is unchecked 41 | * `Create groups` is checked 42 | 43 | This operation could take few minutes as soon as there's a lot of files inside the folders. 44 | 45 | ![](imgs/3.png?raw=true "") 46 | 47 | ##Step 4 48 | 49 | Now let's make some cleanup, so Xcode won't be lagging while processing a lot of not neeed files. 50 | 51 | ###Step 4.1 52 | Inside `Classes` folder choose `Native` folder and search for `.h` files on the bottom of Navigator. 53 | 54 | We need to remove references to `.h` files inside `Native` folder, except those which starts with `"Vuforia"` (they're at the end of the list). I'd recommend not to select and remove all files at once, because Xcode can stuck or even crash :( 55 | 56 | So when pressing `Delete`, make sure to press `Remove References`: 57 | 58 | ![](imgs/4_1.png?raw=true "") 59 | 60 | ###Step 4.2 61 | 62 | Go to `Libraries` folder and remove reference for `libil2cpp` folder. 63 | 64 | Again, make sure to press `Remove References`: 65 | 66 | ![](imgs/4_2.png?raw=true "") 67 | 68 | ##Step 5 69 | Also we need to add some more files from previously Unity-generated iOS project. 70 | 71 | * Drag and drop inside the `Integration` group `Data` folder 72 | * Drag and drop inside the `Integration` group `QCAR` folder wich is in `Data/Raw/` folder 73 | 74 | Check if: 75 | * `Copy resources if needed` is unchecked 76 | * `Create folder references` is checked 77 | 78 | ![](imgs/5_1.png?raw=true "") 79 | 80 | So you will have something like this: 81 | 82 | ![](imgs/5_2.png?raw=true "") 83 | 84 | 85 | ##Step 6 86 | 87 | Add frameworks to the project, so the list will look like this: 88 | 89 | ![](imgs/6.png?raw=true "") 90 | 91 | ##Step 7 92 | 93 | Create `PrefixHeader.pch` file: `File -> New -> Other -> PCH file` 94 | 95 | Remove all code inside and insert the following: 96 | 97 | ``` 98 | #ifndef PrefixHeader_pch 99 | #define PrefixHeader_pch 100 | 101 | #ifdef __OBJC__ 102 | #import 103 | #import 104 | #endif 105 | 106 | #include "Preprocessor.h" 107 | #include "UnityTrampolineConfigure.h" 108 | #include "UnityInterface.h" 109 | 110 | #ifndef __OBJC__ 111 | #if USE_IL2CPP_PCH 112 | #include "il2cpp_precompiled_header.h" 113 | #endif 114 | #endif 115 | 116 | #ifndef TARGET_IPHONE_SIMULATOR 117 | #define TARGET_IPHONE_SIMULATOR 0 118 | #endif 119 | 120 | #define printf_console printf 121 | 122 | #endif 123 | ``` 124 | 125 | Now in the `Build Settings` under `Apple LLVM 7.1 - Language` section, find the field called `Prefix Header` and instead of `/ENTER/PATH/HERE` add path to previously created file, e.g.: `YOUR_PROJECT_NAME/PrefixHeader.pch` which in my case is: `UnityIntegration/PrefixHeader.pch` 126 | 127 | ![](imgs/7.png?raw=true "") 128 | 129 | ##Step 8 130 | 131 | Rename `Supporting Files/main.m` to `main.mm` and `AppDelegate.m` to `AppDelegate.mm` 132 | 133 | ![](imgs/8.png?raw=true "") 134 | 135 | ##Step 9 136 | 137 | Go to `Integration/Classes/main.mm`, copy all code from this file and paste it instead of code in `Supporting Files/main.mm` 138 | 139 | Now, in `Supporting Files/main.mm` change line: `const char* AppControllerClassName = "UnityAppController";` 140 | 141 | with: `const char* AppControllerClassName = "AppDelegate";` 142 | 143 | ##Step 10 144 | 145 | Go to `Build Phases`, search for `"main"` and in `Compile Sources` section remove file which corresponds to `Classes` folder: 146 | 147 | ![](imgs/10.png?raw=true "") 148 | 149 | ##Step 11 150 | 151 | Inside `UnityAppController.h` file make the following changes: 152 | 153 | Comment part: 154 | 155 | ``` 156 | inline UnityAppController* GetAppController() 157 | { 158 | return (UnityAppController*)[UIApplication sharedApplication].delegate; 159 | } 160 | 161 | ``` 162 | 163 | and paste instead: 164 | 165 | 166 | ``` 167 | NS_INLINE UnityAppController* GetAppController() 168 | { 169 | NSObject* delegate = [UIApplication sharedApplication].delegate; 170 | UnityAppController* currentUnityController = (UnityAppController *)[delegate valueForKey:@"unityController"]; 171 | return currentUnityController; 172 | } 173 | ``` 174 | 175 | Inside `UnityAppController.mm` file make the following changes: 176 | 177 | `#import "AppDelegate.h"` 178 | 179 | Replace empty `- (void)shouldAttachRenderDelegate` method with: 180 | 181 | ``` 182 | - (void)shouldAttachRenderDelegate { 183 | 184 | AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate; 185 | [delegate shouldAttachRenderDelegate]; 186 | 187 | } 188 | ``` 189 | 190 | ##Step 12 191 | Inside `VuforiaNativeRendererController.mm` file comment last line: 192 | `IMPL_APP_CONTROLLER_SUBCLASS(VuforiaNativeRendererController)` 193 | 194 | NOTE: If you change something inside your Unity Project, choose Build -> Append. 195 | 196 | After that you need to comment this line in `VuforiaNativeRendererController.mm` again 197 | 198 | ##Step 13 199 | Let's create a button which will open Unity+Vuforia view inside our app. 200 | 201 | In `ViewController.m` add the following parts: 202 | 203 | `#import "AppDelegate.h"` 204 | 205 | `@property (nonatomic, strong) UIButton *showUnityButton;` 206 | 207 | ``` 208 | - (void)viewDidLoad { 209 | [super viewDidLoad]; 210 | self.view.backgroundColor = [UIColor blueColor]; 211 | 212 | self.showUnityButton = [UIButton buttonWithType:UIButtonTypeSystem]; 213 | [self.showUnityButton setTitle:@"SHOW UNITY" forState:UIControlStateNormal]; 214 | self.showUnityButton.frame = CGRectMake(0, 0, 100, 44); 215 | self.showUnityButton.center = self.view.center; 216 | 217 | [self.view addSubview:self.showUnityButton]; 218 | 219 | [self.showUnityButton addTarget:self action:@selector(showUnityButton:) forControlEvents:UIControlEventTouchUpInside]; 220 | 221 | } 222 | 223 | - (void)showUnityButton: (UIButton *) sender { 224 | [(AppDelegate *)[UIApplication sharedApplication].delegate showUnityWindow]; 225 | } 226 | ``` 227 | 228 | ##Step 14 229 | 230 | In this repo you can find both `AppDelegate.h` and `AppDelegate.mm` files and paste their content into your files. 231 | Shortly, what is going on in those files: 232 | 233 | * We create 2 `UIWindow` instances for main and Unity content 234 | * to switch between those windows we use `- (void)showUnityWindow` and `- (void)hideUnityWindow` methods 235 | * also we have instance `unityController` of `UnityAppController` type, because we took away control from Unity-generated app delegate and we need to pass calls to it through our app delegate 236 | * in `(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions ` we create those windows, root view controller, navigation controller etc. so app will work properly 237 | 238 | #Final 239 | Building and running the app will show something like this: we press `Show Unity` button, it opens Unity+Vuforia view which recognizes the marker well and shows nice yellow button in center, which can bring us back to previous view controller 240 | 241 | 242 | ### Useful links 243 | 244 | * [https://the-nerd.be/2015/11/13/integrate-unity-5-in-a-native-ios-app-with-xcode-7/](https://the-nerd.be/2015/11/13/integrate-unity-5-in-a-native-ios-app-with-xcode-7/) 245 | * [http://www.makethegame.net/unity/add-unity3d-to-native-ios-app-with-unity-5-and-vuforia-4-x/](http://www.makethegame.net/unity/add-unity3d-to-native-ios-app-with-unity-5-and-vuforia-4-x/) 246 | * [https://github.com/blitzagency/ios-unity5](https://github.com/blitzagency/ios-unity5) 247 | 248 | -------------------------------------------------------------------------------- /UnityIntegration.xcconfig: -------------------------------------------------------------------------------- 1 | UNITY_IOS_EXPORTED_PATH = /ENTER/PATH/HERE 2 | GCC_PREFIX_HEADER = /ENTER/PATH/HERE; 3 | 4 | UNITY_RUNTIME_VERSION = 5.3.4f1; 5 | UNITY_SCRIPTING_BACKEND = il2cpp; 6 | 7 | OTHER_LDFLAGS = -lc++ -weak_framework CoreMotion -weak-lSystem 8 | 9 | HEADER_SEARCH_PATHS = $(UNITY_IOS_EXPORTED_PATH)/Classes/Native $(UNITY_IOS_EXPORTED_PATH)/Classes $(UNITY_IOS_EXPORTED_PATH) $(UNITY_IOS_EXPORTED_PATH)/Libraries $(UNITY_IOS_EXPORTED_PATH)/Libraries/bdwgc/include $(UNITY_IOS_EXPORTED_PATH)/Libraries/libil2cpp/include 10 | 11 | LIBRARY_SEARCH_PATHS = $(UNITY_IOS_EXPORTED_PATH)/Libraries/Plugins/iOS $(UNITY_IOS_EXPORTED_PATH)/Libraries $(UNITY_IOS_EXPORTED_PATH) 12 | 13 | ENABLE_BITCODE = NO; 14 | 15 | OTHER_CFLAGS = -DINIT_SCRIPTING_BACKEND=1; 16 | OTHER_CPLUSPLUSFLAGS = -DINIT_SCRIPTING_BACKEND=1; 17 | 18 | 19 | CLANG_CXX_LANGUAGE_STANDARD = c++0x; 20 | CLANG_CXX_LIBRARY = libc++; 21 | CLANG_WARN_BOOL_CONVERSION = NO; 22 | CLANG_WARN_CONSTANT_CONVERSION = NO; 23 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; 24 | CLANG_WARN_EMPTY_BODY = NO; 25 | CLANG_WARN_ENUM_CONVERSION = NO; 26 | CLANG_WARN_INT_CONVERSION = NO; 27 | CLANG_WARN_OBJC_ROOT_CLASS = YES; 28 | CLANG_WARN_UNREACHABLE_CODE = NO; 29 | CLANG_WARN__DUPLICATE_METHOD_MATCH = NO; 30 | 31 | GCC_C_LANGUAGE_STANDARD = c99; 32 | GCC_ENABLE_OBJC_EXCEPTIONS = NO; 33 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 34 | GCC_THUMB_SUPPORT = NO; 35 | GCC_USE_INDIRECT_FUNCTION_CALLS = NO; 36 | GCC_WARN_64_TO_32_BIT_CONVERSION = NO; 37 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 38 | GCC_WARN_UNDECLARED_SELECTOR = NO; 39 | GCC_WARN_UNINITIALIZED_AUTOS = NO; 40 | GCC_WARN_UNUSED_FUNCTION = NO; -------------------------------------------------------------------------------- /imgs/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keyv/iOSUnityVuforiaGuide/87a330e7165489cdc2fcce0c5c6ba372087af795/imgs/10.png -------------------------------------------------------------------------------- /imgs/1_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keyv/iOSUnityVuforiaGuide/87a330e7165489cdc2fcce0c5c6ba372087af795/imgs/1_1.png -------------------------------------------------------------------------------- /imgs/1_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keyv/iOSUnityVuforiaGuide/87a330e7165489cdc2fcce0c5c6ba372087af795/imgs/1_2.png -------------------------------------------------------------------------------- /imgs/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keyv/iOSUnityVuforiaGuide/87a330e7165489cdc2fcce0c5c6ba372087af795/imgs/2.png -------------------------------------------------------------------------------- /imgs/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keyv/iOSUnityVuforiaGuide/87a330e7165489cdc2fcce0c5c6ba372087af795/imgs/3.png -------------------------------------------------------------------------------- /imgs/4_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keyv/iOSUnityVuforiaGuide/87a330e7165489cdc2fcce0c5c6ba372087af795/imgs/4_1.png -------------------------------------------------------------------------------- /imgs/4_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keyv/iOSUnityVuforiaGuide/87a330e7165489cdc2fcce0c5c6ba372087af795/imgs/4_2.png -------------------------------------------------------------------------------- /imgs/5_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keyv/iOSUnityVuforiaGuide/87a330e7165489cdc2fcce0c5c6ba372087af795/imgs/5_1.png -------------------------------------------------------------------------------- /imgs/5_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keyv/iOSUnityVuforiaGuide/87a330e7165489cdc2fcce0c5c6ba372087af795/imgs/5_2.png -------------------------------------------------------------------------------- /imgs/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keyv/iOSUnityVuforiaGuide/87a330e7165489cdc2fcce0c5c6ba372087af795/imgs/6.png -------------------------------------------------------------------------------- /imgs/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keyv/iOSUnityVuforiaGuide/87a330e7165489cdc2fcce0c5c6ba372087af795/imgs/7.png -------------------------------------------------------------------------------- /imgs/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keyv/iOSUnityVuforiaGuide/87a330e7165489cdc2fcce0c5c6ba372087af795/imgs/8.png --------------------------------------------------------------------------------