前言
最近接手一個項(xiàng)目,主要是需求就是iOS原生+Unity。網(wǎng)上拖四個文件(Classes、Libraries、MapFileParser.sh、Data)的方式,新版本也是各種報錯。下面說的是一種更簡單方式。
Unity官方給出的操作(有點(diǎn)簡單了)
要將“Unity 用作 iOS 庫”,請像往常一樣,先從 Unity 構(gòu)建 Xcode 項(xiàng)目(有關(guān)更多信息,請參閱 iOS 構(gòu)建設(shè)置)。
每個 Unity iOS Xcode 項(xiàng)目具有以下結(jié)構(gòu):
·UnityFramework 目標(biāo)中的一個庫部分,其中包含源、插件和相關(guān)框架。它還生成 UnityFramework.framework 文件。
· Unity-iPhone 目標(biāo)中的一個瘦啟動器部分,其中包含應(yīng)用程序表示數(shù)據(jù)并會運(yùn)行該庫。Unity-iPhone 目標(biāo)對 UnityFramework 目標(biāo)具有單一依賴關(guān)系。要將 Unity 集成到另一個 Xcode 項(xiàng)目中,必須將兩個 Xcode 項(xiàng)目(原生項(xiàng)目和 Unity 生成的項(xiàng)目)合并到一個 Xcode 工作空間中,并將 UnityFramework.framework 文件添加到原生 Xcode 項(xiàng)目的應(yīng)用程序 (Application) 目標(biāo)的嵌入式二進(jìn)制文件 (Embedded Binaries) 部分中。完成此操作后,可以使用
UnityFramework類來控制 Unity 運(yùn)行時。
上面??的看不懂沒關(guān)系,簡單來說就是將兩個TARGETS 合并在一個workspace里面。下面??開始具體詳細(xì)的步驟。
首先說一下開發(fā)環(huán)境
Xcode:12.5.1
Unity :2020.3.17f1
Unity版本一定要注意,老版本的就按照老前輩們的拖動文件的方式。(老版本集成的方式太惡心人了)
1、創(chuàng)建新的Unity工程并導(dǎo)出Xcode工程(已經(jīng)導(dǎo)出好了,請移步下面??操作2)
為了展示效果,只是簡單創(chuàng)建個buttom在unity。

創(chuàng)建方法點(diǎn)擊左上角加號。這里就不多說了。有興趣的自己研究unity創(chuàng)建物體。
工程創(chuàng)建好之后,就可以導(dǎo)出了。File->Build Setting(快捷鍵:shift + Command +B)
選擇iOS平臺,點(diǎn)擊Player Settings,填寫 Bundle Identifier、和Version。

這邊Bundle Identifier默認(rèn)是 com.Company Name.Product Name,所以你只要對應(yīng)寫一下,會自動生成Bundle Identifie。

點(diǎn)擊下面的Other Settings 設(shè)置具體的運(yùn)行平臺、模擬器還是真機(jī)。

設(shè)置完成之后就可以Bulid了(沒有Build按鈕的,回事一個選擇平臺的按鈕,你一下就出現(xiàn)Build了),如果沒有install iOS平臺,你要install 一下。比如選擇安卓平臺,就會出現(xiàn)下面的界面,你點(diǎn)擊install With Unity Hub就可以了。

剩下的就是Build之后的等待......
導(dǎo)出完成,下面就是導(dǎo)出之后的工程包

打開工程,真機(jī)run一下,沒問題就行,證書這基本配置就不在這說了。
到此第一步就完成了
2、將上面??Unity導(dǎo)出的Xcode 嵌入原生Xcode
為了掩飾,創(chuàng)建新的Xcode工程-iOSUseUnity。將Unity導(dǎo)出的Xcode 復(fù)制到iOSUseUnity下面

如果已經(jīng)通過pods 創(chuàng)建的工程,會有一個xcworkspace,那么就可以忽略下面的操作:
創(chuàng)建xcworkspace(File-> New->workspace),將xcworkspace移動到iOSUseUnity下,然后打開,點(diǎn)擊Xcode左下角的"+"號,將原生工程、unity導(dǎo)出的工程添加進(jìn)來。

如果已經(jīng)pods有workspace后,直接只需要將unity導(dǎo)出的工程添加進(jìn)來就行了,下面是添加完成之后的圖。

添加framework引用Data

編譯一下framework
編譯一下framework
編譯一下framework
Command + B

然后就是在原生工程iOSUseUnity中添加framework。

------------到這基本結(jié)束了工程的配置------------
下面就是上代碼了
main.m
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
NSString * appDelegateClassName;
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:@(argc) forKey:@"argc"];
[userDefaults synchronize];
[userDefaults setObject:[NSString stringWithFormat:@"%p",argv] forKey:@"argv"];
[userDefaults synchronize];
@autoreleasepool {
// Setup code that might create autoreleased objects goes here.
appDelegateClassName = NSStringFromClass([AppDelegate class]);
}
return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}
AppDelegate.h
#import <UIKit/UIKit.h>
#include <UnityFramework/UnityFramework.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate,UnityFrameworkListener>
@property (strong, nonatomic) UIWindow *window;
@property (nonatomic, strong) UnityFramework *ufw;
- (void)showUnityView;
- (void)showNativeView;
@end
AppDelegate.m
#import "AppDelegate.h"
/* UnityFrameworkLoad */
UIKIT_STATIC_INLINE UnityFramework* UnityFrameworkLoad()
{
NSString* bundlePath = nil;
bundlePath = [[NSBundle mainBundle] bundlePath];
bundlePath = [bundlePath stringByAppendingString: @"/Frameworks/UnityFramework.framework"];
NSBundle* bundle = [NSBundle bundleWithPath: bundlePath];
if ([bundle isLoaded] == false) [bundle load];
UnityFramework* ufw = [bundle.principalClass getInstance];
if (![ufw appController])
{
// unity is not initialized
[ufw setExecuteHeader: &_mh_execute_header];
}
return ufw;
}
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
[self initUnity];
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:launchOptions forKey:@"launchOptions"];
[userDefaults synchronize];
return YES;
}
#pragma mark - Unity
- (BOOL)unityIsInitialized
{
return [self ufw] && [[self ufw] appController];
}
- (void)initUnity
{
/* 判斷Unity 是否已經(jīng)初始化 */
if ([self unityIsInitialized]) return;
/* 初始化Unity */
self.ufw = UnityFrameworkLoad();
[self.ufw setDataBundleId:"com.unity3d.framework"];
[self.ufw registerFrameworkListener:self];
// [NSClassFromString(@"FrameworkLibAPI") registerAPIforNativeCalls:self];
NSString *argvStr = [[NSUserDefaults standardUserDefaults] valueForKey:@"argv"];
char **argv;
sscanf([argvStr cStringUsingEncoding:NSUTF8StringEncoding], "%p",&argv);
int argc = [[[NSUserDefaults standardUserDefaults] valueForKey:@"argc"] intValue];
NSDictionary *launchOptions = [[NSUserDefaults standardUserDefaults] valueForKey:@"launchOptions"];
[self.ufw runEmbeddedWithArgc:argc argv:argv appLaunchOpts:launchOptions];
}
- (void)showUnityView
{
if (![self unityIsInitialized]){
NSLog(@"Unity 還未初始化");
}
[self.ufw showUnityWindow];
}
- (void)showNativeView
{
[self.window makeKeyAndVisible];
}
#pragma mark - UnityFrameworkListener
- (void)unityDidUnload:(NSNotification *)notification
{
NSLog(@"========== %s ============",__func__);
[self.window makeKeyAndVisible];
[[self ufw] unregisterFrameworkListener: self];
[self setUfw: nil];
}
- (void)unityDidQuit:(NSNotification *)notification
{
NSLog(@"========== %s ============",__func__);
}
- (void)applicationWillResignActive:(UIApplication *)application {
[[[self ufw] appController] applicationWillResignActive: application];
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
[[[self ufw] appController] applicationDidEnterBackground: application];
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
[[[self ufw] appController] applicationWillEnterForeground: application];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
[[[self ufw] appController] applicationDidBecomeActive: application];
}
- (void)applicationWillTerminate:(UIApplication *)application {
[[[self ufw] appController] applicationWillTerminate: application];
}
@end
添加一個觸發(fā)Unity打開的事件的方法(我這邊是在Main.storyboard添加一個按鈕)。
- (IBAction)btnClick:(UIButton *)sender {
AppDelegate *appDelegate = (AppDelegate *)([UIApplication sharedApplication].delegate);
[appDelegate showUnityView];
}
---------------------------------------常見問題---------------------------------------------
1、#include <UnityFramework/UnityFramework.h> 這一行archive的時候提示file not found?
本人發(fā)的工程只是添加的framework引用,在archive的時候肯定找不到framework。這個時候把unity工程的framework復(fù)制自己工程里面,然后添加引用的時候,從文件夾里添加。

點(diǎn)擊show in finder,找到文件。然后就復(fù)制,拷貝到自己的工程中。

選擇add files,找到你剛才復(fù)制的工程,open 即可。skr~~
通了之后就是這么的簡單,總結(jié)多嘗試,多學(xué)習(xí),不放棄。