React Native與Unity3D的集成需要通過原生程序(iOS 、Android)
這里先介紹iOS中的集成:
首先需要將Unity3D項目導出為iOS項目
Auto Graphic API: 去掉鉤,保留OpenGLES2,刪除其他
Target Device: 根據需要選擇,我這里是默認的iPhone+iPad
Target SDK:一般默認是Device SDK,如果是這個,那么導出之后只能在真機上看效果,我現在是這個,如果你希望能在模擬器上看效果,可以選擇Simulator SDK,不過這樣你就不能發布了。
Scripting Backend:選擇IL2CPP
導出完成后,就有兩個選擇了,一個是修改React Native項目生成的iOS程序,一個是修改Unity3D導出的iOS程序。
<div style={"color : red"}>
這里推薦修改Unity3D導出的iOS程序(修改React Native中的iOS程序,需要修改很多的Build Setting項,編譯容易出錯,非常麻煩)
</div>
修改React Native中的iOS程序
1. 將Unity導出項目里面的Classes、Data、Libraries、MapFileParser、MapFileParser.sh拷貝到ios目錄下面去
2. 打開React Native中ios里面的xcode工程,導入Classes和Libraries,導入時選擇Create groups(.h不需要導入)
3. 導入Data時,需要選擇Create folder reference
4. 設置Xcode的參數:(按照Unity3D導出項目的參數設置)
5. 修改文件
修改Unity3D導出的iOS程序
引入 RCT 相關項目工程到 Libraries 目錄下(可以使用cocoapods)
Build Setting
// 1. 在 Header search path 下添加路徑,類型為 recursive (0.40以下)
$(SRCROOT)/../node_modules/react-native/React
// react native 0.40 后,命名空間有變化,可能需要引入下面的路徑
$(BUILT_PRODUCTS_DIR)/include
// 2. bitcode
enable bitcode : NO
// 3. other linker flag
other linker flag :
$(OTHER_LDFLAGS) -weak_framework CoreMotion -weak-lSystem -ObjC -lc++
// 4. DEBUG宏支持,react native打包以此判斷是否為離線包
Preprocessor Macros > Debug 里設置 "DEBUG=1"
- Build Phases
// 1. 添加 Run Script
// 名稱為
Bundle React Native code and images
// 內容填寫
export NODE_BINARY=node
../node_modules/react-native/packager/react-native-xcode.sh
// 2. Link Binary With Libraries
添加react native組件庫文件,根據需要添加其他庫文件
- Capabilities
// 根據需要打開功能
HealthKit
Push Notification
- 文件修改
// 修改unity3d的UnityAppController.h中(注釋為未修改的)
inline UnityAppController* GetAppController(){
//return (UnityAppController*)[[UIApplication sharedApplication].delegate;
return (UnityAppController*)[[UIApplication sharedApplication] valueForKeyPath:@"delegate.unityAppController"];
}
// 同時需要修改 main.mm
// 引入文件
#import "AppDelegate.h"
// 修改
const char* AppControllerClassName = "AppDelegate";
// 修改AppDelegate文件,添加 unity3d 的初始化和相關處理
// AppDelegate.h
#import "UnityAppController.h"
@property (nonatomic, strong) UnityAppController *unityAppController;
// AppDelegate.m
- (BOOL)application: (UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions{
...
// 添加 unity3d 代碼
BOOL returnBool;
if (_unityAppController == nil) {
_unityAppController = [[UnityAppController alloc]init];
}
returnBool = [_unityAppController application:application didFinishLaunchingWithOptions:launchOptions];
...
}
#pragma mark - same maeeage to unity
-(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];
}
- 其他修改
// debug log去除無用信息
- Xcode menu -> Product -> Edit Scheme -> Arguments
- Environment Variables -> Add -> Name:
"OS_ACTIVITY_MODE", Value:"disable"
//
- 調用 C++ 函數的 .m 文件 (使用GetAppController()方法)要改為 .mm
info.plist 添加
View controller-based status bar appearance
為 NO;react native JS 支持
創建 UIView類用來顯示 unity3d界面,創建react native ViewManager 管理類,使其可以在 JSX 中調用
// RCTUnityView.h
#import <UIKit/UIKit.h>
@interface RCTUnityView : UIView
@property (nonatomic,strong)UIView *uView;
@end
// RCTUnityView.m
#import "RCTUnityView.h"
#import "UnityAppController.h"
@interface RCTUnityView ()
@property (nonatomic,strong) UIView * hide;
@property (nonatomic,strong) NSTimer* timer;
@end
@implementation RCTUnityView
static RCTUnityView * _instance;
-(id)initWithFrame:(CGRect)frame{
if (!_instance) {
_instance = [super initWithFrame:frame];
_instance.uView = (UIView*)GetAppController().unityView;
_instance.uView.frame = frame;
[_instance insertSubview:_instance.uView atIndex:0];
}
return _instance;
}
@end
// RCTUnityViewManager.h
#import "RCTViewManager.h"
@interface RCTUnityViewManager : RCTViewManager
@end
// RCTUnityViewManager.m
#import "RCTUnityViewManager.h"
#import "RCTUIManager.h"
#import "RCTUnityView.h"
#import "UnityAppController.h"
@implementation RCTUnityViewManager
RCT_EXPORT_MODULE();
@synthesize bridge = _bridge;
- (UIView *)view{
return [[RCTUnityView alloc] init] ;
}
- (dispatch_queue_t)methodQueue{
return dispatch_get_main_queue();
}
@end
// UnityViewNative.js
import React, { Component, PropTypes } from 'react';
import {requireNativeComponent,View,Dimensions} from 'react-native';
const RCTUnityView =
requireNativeComponent('RCTUnityView',UnityViewNative);
let screenWidth = Dimensions.get('window').width;
let screenHeight = Dimensions.get('window').height;
export default class UnityViewNative extends Component {
render() {
return <RCTUnityView
style={{width:screenWidth ,height:screenHeight}}
{...this.props}
/>
}
}
- 因為 Unity 3D導出項目與原 React Native 項目名稱不同,react-native run-ios 會失敗,這里需要修改項目的名稱,與 React Native 項目相同,Rename 項目之后,發現運行那里仍然沒有改變,還是不行,點擊 Unity-iphone, 選擇 Manager Schemes,刪除 Unity-iphone, 再添加一個 name 為項目名稱的即可!
可以建立兩個target , 方便debug 和 release 使用