前言
前段时间需要用Unity3D做AR开发展示嵌入的iOS和android中,在过程中碰到了一些问题,现在分享给大家。
准备工作
Unity版本用的是
:Users:sunyujian:Library:Application Support:typora-user-images:image-20221101163609242.png
版本升高之后,在app调试时会crash,无法进行调试,不知道具体的原因是什么,但app release之后是可以使用的。 导入依赖文件
在Unity文件中导入NativeCallProxy的依赖文件。
// NativeCallProxy.h#import <Foundation/Foundation.h>@protocol NativeCallsProtocol@required- (void)iOSLog:(NSString *)value;- (void)backToIOS;@end__attribute__ ((visibility("default")))@interface FrameworkLibAPI: NSObject+(void)registerAPIforNativeCalls:(id<NativeCallsProtocol>) aApi;@end
NativeCallProxy.mm文件
// NativeCallProxy.mm#import <Foundation/Foundation.h>#import "NativeCallProxy.h"@implementation FrameworkLibAPIid<NativeCallsProtocol> api = NULL;+(void)registerAPIforNativeCalls: (id<NativeCallsProtocol>) aApi{ api = aApi;}@endextern "C" { void iOSLog(const char * value);}void iOSLog(const char * value) { return [api iOSLog:[NSString stringWithUTF8String: value]];}extern "C" { void backToIOS(const char * value);}void backToIOS(const char* value) { return [api backToIOS];}
这两个文件导入到Unity3D原文件中,如图所示,放入iOS文件夹下。
image-20221101165709308.png
Unity3D的脚本文件代码如下:
using System.Collections;using System.Collections.Generic;using UnityEngine;using System.Runtime.InteropServices;public class Jiaoben : MonoBehaviour { [DllImport("__Internal")] private static extern void iOSLog(string name); [DllImport("__Internal")] private static extern void backToIOS(); // Unity调用iOS的两个方法,一个是打印log另一个是返回按钮 void Start() { Debug.Log("脚本开始运行"); } // Update is called once per frame void Update() { } // iOS调用Unity的方法。 public void sendArMessage(string msg) { Debug.Log("从iOS接收到的消息:", msg); }}导入iOS工程
将导出的文件拖入到iOS工程中。
image-20221101163857009.png
选中Unity-iPhone中的Data文件,并选中UnityFramework如下图
image-20221101164127269.png
然后选中UnityFramework目标,并点击build按钮进行build。更新UnityFramework文件,如下图。
image-20221101164314307.png
build完成后,选中你的主项目,找到General中的Frameworks,Libraries,and Embedded Content。
image-20221101165048556.png
点击+,在弹出的搜索框中选中UnityFramework.framework,Embed的状态无需改变
:Users:sunyujian:Library:Application Support:typora-user-images:image-20221101165127123.png
最终状态
image-20221101165149961.png
iOS端开发
接下来我们对iOS端的AppDelegate文件进行修改
// AppDelegate.h#import <UIKit/UIKit.h>#include <UnityFramework/UnityFramework.h>#import <UnityFramework/NativeCallProxy.h>@interface AppDelegate : UIResponder <UIApplicationDelegate,UnityFrameworkListener, NativeCallsProtocol>@property (strong, nonatomic) UIWindow * window;@property (strong, nonatomic) UnityFramework *ufw;- (void)showUnityView;- (void)showNativeView;- (void)sendMessageWithName:(const char*)goName functionName:(const char*) functionName message:(const char*)msg;@end
AppDelegate.m
#import "AppDelegate.h"#import "QHJSBaseWebLoader.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]; } [ufw setDataBundleId:"com.unity3d.framework"]; /////////add this code return ufw;}@interface AppDelegate ()@end@implementation AppDelegate- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. [self initUnity]; self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; QHJSBaseWebLoader *rootVc = [[QHJSBaseWebLoader alloc]init]; UINavigationController *rootNav = [[UINavigationController alloc]initWithRootViewController:rootVc]; [rootNav setNavigationBarHidden:YES]; [self.window setRootViewController:rootNav]; [self.window makeKeyAndVisible]; return YES;}// 打印方法-(void)iOSLog:(NSString *)value{ NSLog(@"%@", [NSString stringWithFormat:@"Unity 掉用iOS打印出 :%@",value]);}// 返回按钮-(void)backToIOS { [self showNativeView];}- (UIViewController *) rootViewController { return [[self ufw] appController].rootViewController;}#pragma mark - Unity- (BOOL)unityIsInitialized{ return [self ufw] && [[self ufw] appController];}- (void)initUnity{ /* 判断Unity 是否已经初始化 */ 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];}- (void)sendMessageWithName:(const char*)goName functionName:(const char*) functionName message:(const char*)msg{ [self.ufw sendMessageToGOWithName:goName functionName:functionName message:msg];}#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
调用方法
AppDelegate *appDelegate = (AppDelegate *)([UIApplication sharedApplication].delegate);[appDelegate showUnityView];[appDelegate sendMessageWithName:[@"AR Session Origin" UTF8String] functionName:[@"sendArMessage" UTF8String] message:[message.body UTF8String]];
通过这个调用方法就可以打开新的Unity的页面。 |