APP联合Unity3D实战

APP联合Unity3D实战

总体流程如下:

APP联合Unity3D实战

一.下载Unity无黑Logo版别和东西,不必东西的有黑logo(各端一定要一致啊)

Unity版别:Unity 2022.1.24 unity.com/releases/ed…

无黑LogoPatch下载地址:github.com/tylearymf/U…

二.代码交互相关:

iOS

1.UnitySendMessage代码是这样的:

// objectName: Unity 目标的名称
// methodName: Unity 目标绑定的脚本办法名
// message: 自定义音讯
UnityPlayer.UnitySendMessage(String objectName, String methodName, String message);

该办法有一个弊端,便是发送音讯的办法对应的类,必需求挂载在一个 game object 上。 该办法有一点需求注意,便是在原生触发回调接口的时分,或许跟 Unity 的主线程并不是一个线程,此刻需求告知 Unity 主线程履行回调。

所以回绝运用此办法。以下介绍经过 C# 同名办法反射

2.举个比如:

(1)unity工程 .cs代码

// DllImport这个办法适当所以告知Unity,有一个CallObjCFunc函数在外部会完成。
// 运用这个办法必需求导入System.Runtime.InteropServices;
 [DllImport("__Internal")]
private static extern void takePhotosFromNative(string dictionaryJson);
public override void takePhotosFromNative(string dictionaryJson)
    {
#if UNITY_IOS
        IosNativeAPI.takePhotosFromNative(dictionaryJson);
#endif
    }

每一个办法都要接入[DllImport(“__Internal”)]

(2)unity工程 .mm代码

对应的takePhotosFromNative在oc层

//摄影之后回来小屋
void takePhotosFromNative(const char*dictionaryJson) {
    return [api takePhotosFromNative:[NSString stringWithUTF8String:dictionaryJson]];
}

一定要注意这个 stringWithUTF8String
传入string时分假如传入NSString直接崩溃。

//strdup函数需求引进#import <string.h>
 return strdup([@"abc" UTF8String]) //要调用strdup()函数分配c内存再回来给unity,否则闪退

(3)另一个原生xcode工程的运用:

//摄影之后回来小屋
- (void)takePhotosFromNative:(NSString*)dictionaryJson {
  NSDictionary *dic = [NSString dictionaryWithJsonString:dictionaryJson];
  [self hideUnity];
  JCSUpLoadAvatarViewController *vc = [[JCSUpLoadAvatarViewController alloc]init];
  vc.pageFromWhere = UploadAvatarPageFromUnityPoster;
  vc.posterDic = dic;
  [[UIViewController topmostViewController].navigationController pushViewController:vc animated:YES];
  self.isLogoutFlag = NO;
}

具体代码:

开启unity东西

文件寄存位置 Assets/Scripts/NativeBridge/NativeBridge.cs Assets/Plugins/Android Assets/Plugins/iOS 前面是cs代码,后面是android和iOS代码

交互方法:经过 C# 同名办法反射 Assets/Scripts/NativeBridge/NativeBridge.cs中的代码:

 using System.Runtime.InteropServices;
 using UnityEngine;
 public class NativeAPI
 {
     static CNativeAPI _nativeAPI = null;
     static CNativeAPI nativeAPI
     {
         get
         {
             if (_nativeAPI == null)
             {
 #if UNITY_IOS          
                 _nativeAPI = new CNativeIOS();
 #elif UNITY_ANDROID              
                 _nativeAPI = new CNativeAndroid();
 #else
                 _nativeAPI = new CNativeOther();
 #endif
             }
             return _nativeAPI;
         }
     }
     public static string GetAppHeaderFromNative()
     {
         return nativeAPI.GetAppHeaderFromNative();
     }
     public static void takePhotosFromNative(string dictionaryJson)
     {
         nativeAPI.takePhotosFromNative(dictionaryJson);
     }
     public static void goBackPendingFromNative()
     {
         nativeAPI.goBackPendingFromNative();
     }
     public static void goBackKillFromNative()
     {
         nativeAPI.goBackKillFromNative();
     }
     public static void loginFromNative()
     {
         nativeAPI.loginFromNative();
     }
     public static void hiddenStartUnityLoading()
     {
         nativeAPI.hiddenStartUnityLoading();
     }
 } 
 public abstract class CNativeAPI
 {
     //// 原生办法获取用户信息声明
     public abstract string GetAppHeaderFromNative();
     // 调用相机
     public abstract void takePhotosFromNative(string dictionaryJson);
     // 回来挂起app
     public abstract void goBackPendingFromNative();
     // 回来杀死app
     public abstract void goBackKillFromNative();
     // 登陆
     public abstract void loginFromNative();
     // 隐藏发动加载
     public abstract void hiddenStartUnityLoading();
 }
 public class CNativeIOS : CNativeAPI
 {
     public override string GetAppHeaderFromNative()
     {
 #if UNITY_IOS
         return IosNativeAPI.GetAppHeaderFromNative();
 #else
         return null;
 #endif
     }
     public override void takePhotosFromNative(string dictionaryJson)
     {
 #if UNITY_IOS
         IosNativeAPI.takePhotosFromNative(dictionaryJson);
 #endif
     }
     public override void goBackPendingFromNative()
     {
 #if UNITY_IOS
         IosNativeAPI.goBackPendingFromNative();
 #endif
     }
     public override void goBackKillFromNative()
     {
 #if UNITY_IOS
         IosNativeAPI.goBackKillFromNative();
 #endif
     }
     public override void loginFromNative()
     {
 #if UNITY_IOS
         IosNativeAPI.loginFromNative();
 #endif
     }
     public override void hiddenStartUnityLoading()
     {
         //
     }
 }
 public class CNativeAndroid : CNativeAPI
 {
     public override string GetAppHeaderFromNative()
     {
         return GetAndroidJavaObject().Call<string>("GetAppHeaderFromNative");
     }
     public override void takePhotosFromNative(string dictionaryJson)
     {
         GetAndroidJavaObject().Call("takePhotosFromNative", dictionaryJson);
     }
     public override void goBackPendingFromNative()
     {
         //
     }
     public override void goBackKillFromNative()
     {
         GetAndroidJavaObject().Call("goBackKillFromNative");
     }
     public override void loginFromNative()
     {
         GetAndroidJavaObject().Call("LoginFromNative");
     }
     public override void hiddenStartUnityLoading()
     {
         GetAndroidJavaObject().Call("hiddenStartUnityLoading");
     }
     public AndroidJavaObject GetAndroidJavaObject()
     {
         AndroidJavaClass jc = new AndroidJavaClass("com.company.product.OverrideUnityActivity");
         AndroidJavaObject overrideActivity = jc.GetStatic<AndroidJavaObject>("instance");
         return overrideActivity;
     }
 }
 public class CNativeOther : CNativeAPI
 {
     public override string GetAppHeaderFromNative()
     {
         return "";
     }
     public override void takePhotosFromNative(string dictionaryJson)
     {
         //
     }
     public override void goBackPendingFromNative()
     {
         //
     }
     public override void goBackKillFromNative()
     {
         //
     }
     public override void hiddenStartUnityLoading()
     {
         //
     }
     public override void loginFromNative()
     {
         //
     }
 }
 #if UNITY_IOS
 public static class IosNativeAPI
 {
     //// 在Objective-C中完成的原生办法获取用户信息声明
     [DllImport("__Internal")]
     public static extern string GetAppHeaderFromNative();
     // 在Objective-C中完成调用相机
     [DllImport("__Internal")]
     public static extern void takePhotosFromNative(string dictionaryJson);
     // 在Objective-C中完成回来挂起app
     [DllImport("__Internal")]
     public static extern void goBackPendingFromNative();
     // 在Objective-C中完成回来杀死app
     [DllImport("__Internal")]
     public static extern void goBackKillFromNative();
     // 在Objective-C中完成登陆
     [DllImport("__Internal")]
     public static extern void loginFromNative();
 }
 #endif

Assets/Plugins/iOS中的代码: NativeCallProxy.h

#import <Foundation/Foundation.h>
 // NativeCallsProtocol defines protocol with methods you want to be called from managed
 @protocol NativeCallsProtocol
 //获取token,userid,homeuserid
 - (const char*)GetAppHeaderFromNative;
 //摄影之后回来小屋
 - (void)takePhotosFromNative:(NSString*)dictionaryJson;
 //回来挂起unity
 - (void)goBackPendingFromNative;
 //回来杀死unity
 - (void)goBackKillFromNative;
 //登陆
 - (void)loginFromNative;
 @end
 __attribute__ ((visibility("default")))
 @interface FrameworkLibAPI : NSObject
 // call it any time after UnityFrameworkLoad to set object implementing NativeCallsProtocol methods
 +(void) registerAPIforNativeCalls:(id<NativeCallsProtocol>) aApi;
 @end`

NativeCallProxy.mm代码:

 #import <Foundation/Foundation.h>
 #import "NativeCallProxy.h"
 @implementation FrameworkLibAPI
 id<NativeCallsProtocol> api = NULL;
 +(void) registerAPIforNativeCalls:(id<NativeCallsProtocol>) aApi
 {
     api = aApi;
 }
 @end
 extern "C" {
 //获取token,userid,homeuserid
 const char* GetAppHeaderFromNative(void) {
     return strdup([api GetAppHeaderFromNative]);
 }
 //摄影之后回来小屋
 void takePhotosFromNative(const char*dictionaryJson) {
     return [api takePhotosFromNative:[NSString stringWithUTF8String:dictionaryJson]];
 }
 //回来挂起unity
 void goBackPendingFromNative(void) {
     return [api goBackPendingFromNative];
 }
 //回来杀死unity
 void goBackKillFromNative(void) {
     return [api goBackKillFromNative];
 }
 // 登录
 void loginFromNative(void) {
     return [api loginFromNative];
 }
 } `

三.履行打包:挑选file 下的build setting

APP联合Unity3D实战

然后挑选iOS下的build

APP联合Unity3D实战

假如代码没报错的话,那么恭喜你unity打包出来能够直接运转在xcode上了。

四.打出来的Unity-iPhone.xcodeproj工程集成到另一个工程中。

1.iOS手动修正装备到另一个工程:

(1)将打出来的包unity一切文件整个移动到另一个工程的unity3d目录下。

APP联合Unity3D实战

(2)设置data的target为framework

APP联合Unity3D实战

(3)修正unity的target为JRDebug_UAT和JRRelease_ProductSever (假如主工程GoHome没有装备多scheme环境的不必设置)

APP联合Unity3D实战

以下为主工程设置(与unity无关)

APP联合Unity3D实战

(4)unity framework的navtiveCallProxy.h设置为public

APP联合Unity3D实战
假如这个中心头文件在project中私有的话,要提到public中,framework要揭露头文件

(5)运转下unity工程

sucess

(6)运转下ios工程(假如改动不成功,就把iOS的unityframework删除,从头增加下)

APP联合Unity3D实战

2.iOS经过脚本修正装备到另一个工程:

APP联合Unity3D实战

(1)build_move_file.sh文件

#第一步:修正unity导出来后的装备

ruby change_target_membership.rb

#第二步:编译framework

xcodebuild -project unity3d/Unity-iPhone.xcodeproj -target UnityFramework -configuration Release

echo “n —- 第二步,编译framework成功 —- n”

#第三步:增加framework到主工程中

ruby add_unityframework_native.rb

####(2)设置data的target为framework + 修正NativeCallProxy类为揭露类 change_target_membership.rb文件

require ‘xcodeproj’

翻开Xcode项目

project_path = ‘unity3d/Unity-iPhone.xcodeproj’

project = Xcodeproj::Project.open(project_path)

第一步:修正Data文件的targets

找到对应的targets

unity_iphone_target = project.targets.find { |target| target.name == ‘Unity-iPhone’ }

unity_framework_target = project.targets.find { |target| target.name == ‘UnityFramework’ }

查找 Data 文件夹的引证

data_group = project.main_group.find_subpath(‘Data’, false)

这是 rough check,保证 data_group 的确指向你想要改动 target membership 的目录

raise ‘Data directory not found’ unless data_group

将 Data 文件夹增加到 unity_framework_target

unity_framework_target.add_resources([data_group])

第一步完毕

第二步:修正NativeCallProxy类为揭露类

找到NativeCallProxy.h文件

native_call_proxy_h_ref = project.files.find { |file| file.name == ‘NativeCallProxy.h’ }

raise ‘NativeCallProxy.h file not found’ unless native_call_proxy_h_ref

获取 headers build phase

headers_build_phase = unity_framework_target.build_phases.find { |bp| bp.class == Xcodeproj::Project::Object::PBXHeadersBuildPhase }

查找或创建一个 headers group

headers_group = project.main_group.find_subpath(‘Headers’, true)

设置NativeCallProxy.h为Public

native_call_proxy_h_ref.build_files.each do |build_file|

build_file.settings = { ‘ATTRIBUTES’ => [‘Public’] } if build_file.file_ref.real_path == native_call_proxy_h_ref.real_path

end

第二步完毕

保存项目

project.save

####(3) 增加framework到主工程中 add_unityframework_native.rb文件

require 'xcodeproj'

翻开现有的Xcode项目

project_path = ‘GoHome.xcodeproj’

project = Xcodeproj::Project.open(project_path)

找到你要增加框架的目标

target = project.targets.find { |t| t.name == ‘GoHome’ }

指定要增加的新Framework路径

new_framework_path = ‘unity3d/build/Release-iphoneos/UnityFramework.framework’

定位到Frameworks引证组,这取决于你项目的实践结构

framework_group = project.frameworks_group

查找并删除现有的UnityFramework.framework引证

exist_framework_ref = framework_group.files.find { |file| file.path =~ /UnityFramework.framework/ }

if exist_framework_ref

从构建阶段中移除

target.frameworks_build_phases.remove_file_reference(exist_framework_ref)

从项目引证中移除

framework_group.children.delete(exist_framework_ref)

实践删除文件引证

exist_framework_ref.remove_from_project

end

增加新的UnityFramework.framework引证

framework_reference = framework_group.new_file(new_framework_path)

将framework增加到目标的’Frameworks’构建阶段中

target.frameworks_build_phases.add_file_reference(framework_reference, true)

保证新增加的Framework被设置为”Embed & Sign”

attributes = [‘CodeSignOnCopy’, ‘RemoveHeadersOnCopy’]

embed_frameworks_build_phase = target.build_phases.find { |bp| bp.is_a?(Xcodeproj::Project::Object::PBXCopyFilesBuildPhase) && bp.symbol_dst_subfolder_spec == :frameworks }

假如没有找到嵌入的构建阶段,就创建一个

unless embed_frameworks_build_phase

embed_frameworks_build_phase = project.new(Xcodeproj::Project::Object::PBXCopyFilesBuildPhase)

embed_frameworks_build_phase.name = ‘Embed Frameworks’

embed_frameworks_build_phase.symbol_dst_subfolder_spec = :frameworks

target.build_phases << embed_frameworks_build_phase

end

增加文件引证到那个构建阶段

build_file = embed_frameworks_build_phase.add_file_reference(framework_reference)

build_file.settings = { ‘ATTRIBUTES’ => attributes }

将改动保存到Xcode项目文件

project.save puts ‘ —- 最终一步,替换Framework成功 —- ‘

以上运转到了原生工程中,接下来是原生代码中具体运用。

1.封装中心类

JCSUnityManager.h代码

 #import <Foundation/Foundation.h>
 #include <UnityFramework/UnityFramework.h>
 #include <UnityFramework/NativeCallProxy.h>
 NS_ASSUME_NONNULL_BEGIN
 @interface JCSUnityManager : UIResponder<UIApplicationDelegate,UnityFrameworkListener,NativeCallsProtocol>
 + (instancetype _Nullable )shareInstance;
 -(void) setLaunchConfigs:(UIWindow *)utWindow launchOptions:(NSDictionary *)options;
 -(void)firstTimePrepareUnity:(void(^)(BOOL completed))completion;
 -(void) prepareUnity:(void(^)(BOOL completed))completion;
 -(void) pauseUnity:(BOOL)paused;
 -(void) hideUnity;
 -(void) quitUnity:(void(^)())completion;
 -(void) unloadUnity;
 - (bool)unityIsInitialized;
 -(void) sendMessage:(NSString *)clsName Method:(NSString *)method Message:(NSString *)message;
 -(UIViewController *) getUnityRootViewController;
 -(UIView *) getUnityView;
 @property (nonatomic, strong) UnityFramework *unityFwk;
 @property(nonatomic, assign) BOOL isLogoutFlag;
 //获取token,userid,homeuserid
 - (const char*)GetAppHeaderFromNative;
 //摄影之后回来小屋
 - (void)takePhotosFromNative:(NSString*)dictionaryJson;
 //回来挂起unity
 - (void)goBackPendingFromNative;
 //回来杀死unity
 - (void)goBackKillFromNative;
 //登陆
 - (void)loginFromNative;
 @end
 NS_ASSUME_NONNULL_END`

JCSUnityManager.m代码

 #import "JCSUnityManager.h"
 #import "AppDelegate.h"
 #import "AppDelegate+Event.h"
 #import "JRLoginViewModel.h"
 #import "JCSUpLoadAvatarViewController.h"
 #import "NSString+Help.h"
 @interface JCSUnityManager()
 @property(nonatomic,strong) UIWindow *hostWindow;
 @property(nonatomic,strong) NSDictionary *launchOpts;
 @property (nonatomic, strong) JRLoginViewModel *viewModel;
 @end
 @implementation JCSUnityManager
 /** 单例 */
 + (instancetype)shareInstance{
     static JCSUnityManager *instance = nil;
     static dispatch_once_t onceToken;
     _dispatch_once(&onceToken, ^{
         instance = [[JCSUnityManager alloc] init];
     });
     return instance;
     }
 -(void)setLaunchConfigs:(UIWindow *)utWindow launchOptions:(NSDictionary *)options {
     self.hostWindow = utWindow;
     self.launchOpts = options;
 }
 - (bool)unityIsInitialized {
     // 判斷是否已經初始化過Unity執行環境
     return self.unityFwk && [self.unityFwk appController];
     }
 - (void)initUnity:(void(^)(BOOL completed))completion {
     // 初始化Unity執行環境
     if([self unityIsInitialized]) {
         completion(true);
         return;
     }
     self.unityFwk = [self loadUnityFramework];
     [self.unityFwk setDataBundleId:"com.unity3d.framework"];
     [self.unityFwk registerFrameworkListener:self];
     [NSClassFromString(@"FrameworkLibAPI") registerAPIforNativeCalls:self];
     // 获得APP執行參數
     NSArray *arguments = [[NSProcessInfo processInfo] arguments];
     int argc = (int)arguments.count;
     [self.unityFwk runEmbeddedWithArgc:argc argv:[self getChar:arguments] appLaunchOpts: self.launchOpts];
     completion(true);
     }
 -(UIViewController *) getUnityRootViewController {
     return [[self.unityFwk appController] rootViewController];
 }
 -(UIView *)getUnityView {
     return [self getUnityRootViewController].view;
 }
 -(void)firstTimePrepareUnity:(void(^)(BOOL completed))completion {
     // 準備Unity執行環境並執行
     if (![self unityIsInitialized]) {
         [self initUnity:^(BOOL completed) {             if (completed) {                 dispatch_async(dispatch_get_main_queue(), ^{                     completion(true);                 });             }         }];
     } else {
         dispatch_async(dispatch_get_main_queue(), ^{
             completion(true);
         });
     }
 }
 -(void) prepareUnity:(void(^)(BOOL))completion {
     // 準備Unity執行環境並執行
     if (![self unityIsInitialized]) {
         [self initUnity:^(BOOL completed) {             if (completed) {                 [self.unityFwk showUnityWindow];
                                dispatch_async(dispatch_get_main_queue(), ^{
                     completion(true);
                 });
             }
         }];
     } else {
         [self.unityFwk showUnityWindow];
         dispatch_async(dispatch_get_main_queue(), ^{
             completion(true);
         });
     }
 }
 -(void) sendMessage:(NSString *)clsName Method:(NSString *)method Message:(NSString *)message {
     [self.unityFwk sendMessageToGOWithName:clsName.UTF8String functionName:method.UTF8String message:message.UTF8String];
 }
 -(void) hideUnity {
     if (self.hostWindow != nil) {
         [self.hostWindow makeKeyAndVisible];
     }
 }
 -(void) pauseUnity:(BOOL)paused {
     if (self.unityFwk != nil) {
         [self.unityFwk pause:paused];
     }
 }
 -(void) quitUnity:(void(^)())completion {
     if ([self unityIsInitialized]) {
         [self.unityFwk appController].quitHandler = ^{
             NSLog(@"AppController.quitHandler called");
             dispatch_async(dispatch_get_main_queue(), ^{
                 completion();
             });
         };
         [self.unityFwk quitApplication:0];
     }
 }
 - (void) unloadUnity {
     if ([self unityIsInitialized]) {
         [self.unityFwk unloadApplication];
     }
     }
 #pragma mark - 清掉Listener
 - (void)unityDidUnload:(NSNotification*)notification
   {
     NSLog(@"unityDidUnloaded called");
     if (self.hostWindow != nil) {
         [self.hostWindow makeKeyAndVisible];
     }
     [self.unityFwk unregisterFrameworkListener:self];
     self.unityFwk = nil;
     if(self.isLogoutFlag) {
         [JCSCommonTool clearLocalData];
         self.isLogoutFlag = NO;
     }
 //    [self setUnityFwk: nil];
 }
 - (void)unityDidQuit:(NSNotification *)notification
 {
     NSLog(@"========== %s ============",__func__);
     if (self.hostWindow != nil) {
         [self.hostWindow makeKeyAndVisible];
     }
 }
 - (UnityFramework *) loadUnityFramework {
     // 載入UnityFramework
     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;
     }
 - (char**)getChar:(NSArray *) a_array{
     NSUInteger count = [a_array count];
     char **array = (char **)malloc((count + 1) * sizeof(char*));
     for (unsigned i = 0; i < count; i++)
     {
         array[i] = strdup([[a_array objectAtIndex:i] UTF8String]);
     }
     array[count] = NULL;
     return array;
     }
 - (void)applicationWillResignActive:(UIApplication *)application {
     [[[JCSUnityManager shareInstance].unityFwk appController] applicationWillResignActive: application];
     }
 - (void)applicationDidEnterBackground:(UIApplication *)application {
     [[[JCSUnityManager shareInstance].unityFwk appController]applicationDidEnterBackground: application];
     }
 - (void)applicationWillEnterForeground:(UIApplication *)application {
     [[[JCSUnityManager shareInstance].unityFwk appController] applicationWillEnterForeground: application];
     }
 - (void)applicationDidBecomeActive:(UIApplication *)application {
     [[[JCSUnityManager shareInstance].unityFwk appController] applicationDidBecomeActive: application];
     }
 - (void)applicationWillTerminate:(UIApplication *)application {
     [[[JCSUnityManager shareInstance].unityFwk appController] applicationWillTerminate: application];
     }
 #pragma mark - NativeCallsProtocol
 //获取token,userid,homeuserid
 - (const char*)GetAppHeaderFromNative
 {
     self.isLogoutFlag = NO;
     NSMutableDictionary *dictionary = [[NSMutableDictionary alloc]init];
     // token
     NSString *authorization = [JRAccountManager authorization];
     [dictionary setValue:authorization forKey:@"Authorization"];
     [dictionary setValue:[JRAccountManager memberId] forKey:@"userId"];
     NSString *roomHostId = [JCSCommonTool getUnityCurrentUserId];
     if(roomHostId && ![roomHostId isEqualToString:[JRAccountManager memberId]]) {
         [dictionary setValue:roomHostId forKey:@"roomHostId"];
     }
     else {
         [dictionary setValue:[JRAccountManager memberId] forKey:@"roomHostId"];
     }
     NSString *str = [JRAPIManager hostUrl];
     [dictionary setValue:str forKey:@"hostUrl"];
     NSLog(@"dictionary==%@",dictionary);
     NSError *error;
     NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:&error];
     NSString *dicString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
     const char *temp11 = [dicString UTF8String];
     //    [[self ufw] sendMessageToGOWithName: "Cube" functionName: "ReceiveHeaderDictionaryFromiOS" message: temp11];
     return temp11;
 }
 //摄影之后回来小屋
 - (void)takePhotosFromNative:(NSString*)dictionaryJson {
   //    NSLog(@"摄影%@",dictionaryJson);
     NSDictionary *dic = [NSString dictionaryWithJsonString:dictionaryJson];
   //    NSMutableDictionary *muDic = [[NSMutableDictionary alloc]initWithDictionary:dic];
   //    NSLog(@"摄影dic%@",dic);
   //    [self pauseUnity:YES];
     [self hideUnity];
     JCSUpLoadAvatarViewController *vc = [[JCSUpLoadAvatarViewController alloc]init];
     vc.pageFromWhere = UploadAvatarPageFromUnityPoster;
     vc.posterDic = dic;
     [[UIViewController topmostViewController].navigationController pushViewController:vc animated:YES];
     self.isLogoutFlag = NO;
 }
 //回来挂起unity
 - (void)goBackPendingFromNative {
     self.isLogoutFlag = NO;
 }
 //回来杀死unity
 - (void)goBackKillFromNative {
 //    [self quitUnity:^{
 //        NSLog(@"%@",self.unityFwk);
 //    }];
    [self unloadUnity];
     self.isLogoutFlag = NO;
 //    [self hideUnity];
 }
 //登陆
 - (void)loginFromNative {
     NSLog(@"登录");
     [self unloadUnity];
     self.isLogoutFlag = YES;
 }`

2.appdelegate预加载unity:(避免黑屏或者闪屏等待时间过长,需求unity退出时毁掉干净场景的大局资源)

APP联合Unity3D实战

   [[JCSUnityManager shareInstance]firstTimePrepareUnity:^(BOOL completed) {
        [[JCSUnityManager shareInstance] unloadUnity];
    }];
    [[JCSUnityManager shareInstance]setLaunchConfigs:self.window launchOptions:launchOptions];

Android

1、下载和解压项目

这个项目里有一个跟安卓原生运用一同工作的UnityPlayerActivity的扩展,叫OverrideUnityActivity。这个Unity项目会被咱们嵌入到Android Studio的一个根底的运用模板中,它就像任何一个带用户界面的Android运用那样,经过Intent的方法发动Unity部分。 咱们供给的原生Android项目是来自Android Studio模板的Basic Activity运用程序,咱们会把前面的Unity项目加入到这里。该项目有UI和MainUnityActivity来扩展OverrideUnityActivity,能够运用Intent发动MainUnityActivity。

  1. 把Unity项目和原生Android项目解压到同一个文件夹里使得后续操作更简单。

APP联合Unity3D实战

2、生成Android渠道的Gradle项目

在Unity中翻开这个项目,导航到“Build Settings”,切换到安卓渠道而且勾选“Export Project”来导出项目。

APP联合Unity3D实战

当Unity项目导出之后,你会得到包含了unityLibrary模块的androidBuild文件夹。。

APP联合Unity3D实战

3、把Unity Library模块增加到NativeAndroidApp

现在你要做的是,将unityLibrary模块增加到你的原生Android项目中去。你能够经过修正Android Studio项目的settings.gradle文件来完成,只需在文件最终增加上一行代码来包含unityLibrary

include ':unityLibrary'
project(':unityLibrary').projectDir=new File('..UnityProjectandroidBuildunityLibrary') 

APP联合Unity3D实战

之后,更新app模块的build.gradle文件来声明对unityLibrary模块的依靠。

implementation project(':unityLibrary')

APP联合Unity3D实战

翻开build.gradle文件,把下面代码增加到allprojects{repositories{代码块。

flatDir {
   dirs "${project(':unityLibrary').projectDir}/libs"
}

APP联合Unity3D实战

Gradle文件现已修正,单击Sync Now。

APP联合Unity3D实战

修正完后,同步Gradle,这样unityLibrary就被加入到项目中了。

APP联合Unity3D实战

  1. 你现在能够测验构建并运转运用了。假如一切顺利,运用应当能够正常发动和运转。

APP联合Unity3D实战

假如一切顺利,咱们应该能够运转NativeAndroidApp。

APP联合Unity3D实战

请注意:在运用程序装置到设备后,会呈现二个发动运用程序的图标,请把…从unityLibrary的AndroidManifest.xml去掉,仅保存集成版别。

当你完成集成并装置运用到你的设备之后,你或许会注意到有两个发动图标呈现。这通常是因为unityLibrary模块的AndroidManifest.xml文件中定义了一个额定的发动器入口。你需求做的是,去掉这个剩余的入口,只保存你的原生Android运用需求的那部分。这样做你的运用就只会有一个发动图标了。

别的,假如你在将Unity项目集成到原生Android运用的过程中遇到了任何难题,一个处理的办法是运用一个全面装备好的完好项目。你能够下载这个完好的项目文件包,解压后,在Android Studio中翻开NativeAndroidApp。这个完好的项目现已设置好了所需的一切装备,而且能够直接构建和布置。这样就能够省去你手动整合的费事,特别是假如你是第一次测验这样做或是对整个流程不是很熟悉的话。运用完好项目作为起点,能够协助你更容易地理解整合过程,而且保证你有一个安稳的根底来进行后续的开发和调试。

参阅Unity完好项目地址:

请访问云盘下载示例项目

下载链接:pan.baidu.com/s/1JFWjbrh2…