ReactNative集成Unity3D
首先版本号
React Native 版本 0.59.0
Unity3D 版本 2019.3.4f1
这里我们先看Unity3D导出工程的设置
首先我们先建立一个项目,这里我随便建立一个Unity3D项目,如下图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eAOpAFj0-1597387382192)(http://loveit.cool:10088/unity86.png)]
然后我们选择File — Build Settings — iOS — Player Settings,这里我们可以设置打包是release还是debug版本
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WpxRYCvu-1597387382197)(http://loveit.cool:10088/unity87.png)]
点击Player Settings后会弹出一下面板,这里有几个需要注意的地方
1.首先 Auto Graphics API 去掉勾选,下面Graphics API去掉metal选择OpenGLES2
2.Bundle ID 和版本号要写成和你集成app一样的ID和版本号
3.Target SDK 选择设备的SDK,否则无法打包发布以及最低版本号支持
4.Strip Engine Code 去掉勾选,此处不对代码打包优化,否则有的静态库会缺失
以上操作完毕之后直接点击build打包即可(这里根据项目大小,等待时间不一)
完成打包后会生成以下文件
接下来我们回到IOS工程
首先我们用rn新建一个ios项目
react-native init r nunity --verbose --version 0.59.0
新建好项目后,这是我的目录结构,我们找到ios目录
点击打开上图中的ios文件夹,把unity3d工程生成的几个文件复制过来,下午红色框为复制过来的文件
然后我们用xcode打开新建的rn项目,导入一下包,注意要用两种方式导入
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7yl7dVW5-1597387382205)(http://106.13.63.7:10088/unity94.png)]
导入完成后为这个样子
这里我们要删除Libraries里面的ibil2cpp文件夹下的所有引用,注意这里是删除引用 不是删除文件,如下
然后我们就要引入.framework文件,如下图,注意有三个需要调成Option的,不调整会报错
然后切换到Build Setting设置以下属性
Enable Bitcode : NO
Other C Flags
Other C++ Flags
设置以下属性
-DINIT_SCRIPTING_BACKEND=1
-DRUNTIME_IL2CPP=1
-DNET_4_0
-fexceptions
prefix的设置,参考下图
设置unity版本号等信息,一共四项根据你的项目版本设置
GCC_THUMB_SUPPORT NO
GCC_USE_INDIRECT_FUNCTION_CALLS NO
UNITY_RUNTIME_VERSION 2019.3.4f1
UNITY_SCRIPTING_BACKEND il2cpp
添加Run Script
"$PROJECT_DIR/MapFileParser.sh"
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7jLxn2k0-1597387382211)(http://106.13.63.7:10088/unity101.png)]
main.mm文件的处理
首先复制Classes里面的main.mm文件内容
然后删除Classes里main.mm文件的引用
同时修改app文件的maim.m 把复制的黏贴过来
然后删除app中的main.m文件的引用
将app中的main.m文件改名为main.mm
然后加入到引用中即可,以下为代码
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#include "RegisterFeatures.h"
#include <csignal>
#include "UnityInterface.h"
#include "../UnityFramework/UnityFramework.h"
void UnityInitTrampoline();
// WARNING: this MUST be c decl (NSString ctor will be called after +load, so we cant really change its value)
const char* AppControllerClassName = "AppDelegate";
int main(int argc, char * argv[]) {
@autoreleasepool {
UnityInitTrampoline();
UnityInitRuntime(argc,argv);
RegisterFeatures();
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
#if UNITY_USES_DYNAMIC_PLAYER_LIB
extern "C" void SetAllUnityFunctionsForDynamicPlayerLib();
#endif
extern "C" void UnitySetExecuteMachHeader(const MachHeader* header);
extern "C" __attribute__((visibility("default"))) NSString* const kUnityDidUnload;
extern "C" __attribute__((visibility("default"))) NSString* const kUnityDidQuit;
@implementation UnityFramework
{
int runCount;
}
UnityFramework* _gUnityFramework = nil;
+ (UnityFramework*)getInstance
{
if (_gUnityFramework == nil)
{
_gUnityFramework = [[UnityFramework alloc] init];
}
return _gUnityFramework;
}
- (UnityAppController*)appController
{
return GetAppController();
}
- (void)setExecuteHeader:(const MachHeader*)header
{
UnitySetExecuteMachHeader(header);
}
- (void)sendMessageToGOWithName:(const char*)goName functionName:(const char*)name message:(const char*)msg
{
UnitySendMessage(goName, name, msg);
}
- (void)registerFrameworkListener:(id<UnityFrameworkListener>)obj
{
#define REGISTER_SELECTOR(sel, notif_name) \
if([obj respondsToSelector:sel]) \
[[NSNotificationCenter defaultCenter] addObserver:obj selector:sel name:notif_name object:nil];
REGISTER_SELECTOR(@selector(unityDidUnload:), kUnityDidUnload);
REGISTER_SELECTOR(@selector(unityDidQuit:), kUnityDidQuit);
#undef REGISTER_SELECTOR
}
- (void)unregisterFrameworkListener:(id<UnityFrameworkListener>)obj
{
[[NSNotificationCenter defaultCenter] removeObserver: obj name: kUnityDidUnload object: nil];
[[NSNotificationCenter defaultCenter] removeObserver: obj name: kUnityDidQuit object: nil];
}
- (void)frameworkWarmup:(int)argc argv:(char*[])argv
{
#if UNITY_USES_DYNAMIC_PLAYER_LIB
SetAllUnityFunctionsForDynamicPlayerLib();
#endif
UnityInitTrampoline();
UnityInitRuntime(argc, argv);
RegisterFeatures();
// iOS terminates open sockets when an application enters background mode.
// The next write to any of such socket causes SIGPIPE signal being raised,
// even if the request has been done from scripting side. This disables the
// signal and allows Mono to throw a proper C# exception.
std::signal(SIGPIPE, SIG_IGN);
}
- (void)setDataBundleId:(const char*)bundleId
{
UnitySetDataBundleDirWithBundleId(bundleId);
}
- (void)runUIApplicationMainWithArgc:(int)argc argv:(char*[])argv
{
self->runCount += 1;
[self frameworkWarmup: argc argv: argv];
UIApplicationMain(argc, argv, nil, [NSString stringWithUTF8String: AppControllerClassName]);
}
- (void)runEmbeddedWithArgc:(int)argc argv:(char*[])argv appLaunchOpts:(NSDictionary*)appLaunchOpts
{
if (self->runCount)
{
// initialize from partial unload ( sceneLessMode & onPause )
UnityLoadApplicationFromSceneLessState();
[self pause: false];
[self showUnityWindow];
}
else
{
// full initialization from ground up
[self frameworkWarmup: argc argv: argv];
id app = [UIApplication sharedApplication];
id appCtrl = [[NSClassFromString([NSString stringWithUTF8String: AppControllerClassName]) alloc] init];
[appCtrl application: app didFinishLaunchingWithOptions: appLaunchOpts];
[appCtrl applicationWillEnterForeground: app];
[appCtrl applicationDidBecomeActive: app];
}
self->runCount += 1;
}
- (void)unloadApplication
{
UnityUnloadApplication();
}
- (void)quitApplication:(int)exitCode
{
UnityQuitApplication(exitCode);
}
- (void)showUnityWindow
{
[[[self appController] window] makeKeyAndVisible];
}
- (void)pause:(bool)pause
{
UnityPause(pause);
}
@end
#if TARGET_IPHONE_SIMULATOR && TARGET_TVOS_SIMULATOR
#include <pthread.h>
extern "C" int pthread_cond_init$UNIX2003(pthread_cond_t *cond, const pthread_condattr_t *attr)
{ return pthread_cond_init(cond, attr); }
extern "C" int pthread_cond_destroy$UNIX2003(pthread_cond_t *cond)
{ return pthread_cond_destroy(cond); }
extern "C" int pthread_cond_wait$UNIX2003(pthread_cond_t *cond, pthread_mutex_t *mutex)
{ return pthread_cond_wait(cond, mutex); }
extern "C" int pthread_cond_timedwait$UNIX2003(pthread_cond_t *cond, pthread_mutex_t *mutex,
const struct timespec *abstime)
{ return pthread_cond_timedwait(cond, mutex, abstime); }
#endif // TARGET_IPHONE_SIMULATOR && TARGET_TVOS_SIMULATOR
然后Prefix.pch加上如下引用
#import "UnityAppController.h"
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rxQaJ5JB-1597387382213)(http://106.13.63.7:10088/unity103.png)]
Appdelegate.h如下修改
#import <React/RCTBridgeDelegate.h>
#import <UIKit/UIKit.h>
@class UnityAppController;
@interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate>
@property (nonatomic, strong) UIWindow *window;
@property (nonatomic, strong) UIWindow *unityWindow;
@property (nonatomic, strong) UIWindow *unityController;
@end
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZasyV2GZ-1597387382214)(http://106.13.63.7:10088/unity104.png)]
Appdelegate.m如下修改
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import "AppDelegate.h"
#import "UnityAppController.h"
#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
@implementation AppDelegate
- (UIWindow *)unityWindow
{
return UnityGetMainWindow();
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
moduleName:@"rnunity"
initialProperties:nil];
rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
_UnityAppController = [[UnityAppController alloc]init];//这里初始化unity
[_UnityAppController application:application didFinishLaunchingWithOptions:launchOptions];
self.window = _UnityAppController.window;
// [self.window makeKeyAndVisible];
return YES;
}
-(void)applicationWillResignActive:(UIApplication *)application{
[_UnityAppController applicationWillResignActive:application];
}
-(void)applicationDidEnterBackground:(UIApplication *)application{
[_UnityAppController applicationDidEnterBackground:application];
}
-(void)applicationWillEnterForeground:(UIApplication *)application{
[_UnityAppController applicationWillEnterForeground:application];
}
-(void)applicationDidBecomeActive:(UIApplication *)application{
[_UnityAppController applicationDidBecomeActive:application];
}
-(void)applicationWillTerminate:(UIApplication *)application{
[_UnityAppController applicationWillTerminate:application];
}
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}
@end
运行的时候设置为release版本即可
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZKcWMswK-1597387382216)(http://106.13.63.7:10088/unity106.png)]
运行效果