diff --git a/ios/RNUnity.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/RNUnity.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/ios/RNUnity.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/ios/RNUnity/RNUnity.xcodeproj/project.pbxproj b/ios/RNUnity/RNUnity.xcodeproj/project.pbxproj
index 92b8359..f7f985d 100644
--- a/ios/RNUnity/RNUnity.xcodeproj/project.pbxproj
+++ b/ios/RNUnity/RNUnity.xcodeproj/project.pbxproj
@@ -9,6 +9,8 @@
/* Begin PBXBuildFile section */
0053E483231940930014F962 /* UnityResponderView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0053E482231940930014F962 /* UnityResponderView.m */; };
0053E4862319420A0014F962 /* UnityResponderViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0053E4852319420A0014F962 /* UnityResponderViewManager.m */; };
+ 7261D468277A43BA00D323AC /* UnityNativeModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 7261D467277A43BA00D323AC /* UnityNativeModule.m */; };
+ 7261D46B277A43FD00D323AC /* UnityUtils.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7261D46A277A43FD00D323AC /* UnityUtils.mm */; };
B3E7B58A1CC2AC0600A0062D /* RNUnity.m in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* RNUnity.m */; };
/* End PBXBuildFile section */
@@ -30,6 +32,10 @@
0053E4852319420A0014F962 /* UnityResponderViewManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UnityResponderViewManager.m; sourceTree = ""; };
0053E4872319422D0014F962 /* UnityResponderViewManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UnityResponderViewManager.h; sourceTree = ""; };
134814201AA4EA6300B7C361 /* libRNUnity.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNUnity.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ 7261D466277A438500D323AC /* UnityNativeModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UnityNativeModule.h; sourceTree = ""; };
+ 7261D467277A43BA00D323AC /* UnityNativeModule.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UnityNativeModule.m; sourceTree = ""; };
+ 7261D469277A43E800D323AC /* UnityUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UnityUtils.h; sourceTree = ""; };
+ 7261D46A277A43FD00D323AC /* UnityUtils.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = UnityUtils.mm; sourceTree = ""; };
B3E7B5881CC2AC0600A0062D /* RNUnity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNUnity.h; sourceTree = ""; };
B3E7B5891CC2AC0600A0062D /* RNUnity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNUnity.m; sourceTree = ""; };
/* End PBXFileReference section */
@@ -56,6 +62,10 @@
58B511D21A9E6C8500147676 = {
isa = PBXGroup;
children = (
+ 7261D46A277A43FD00D323AC /* UnityUtils.mm */,
+ 7261D469277A43E800D323AC /* UnityUtils.h */,
+ 7261D466277A438500D323AC /* UnityNativeModule.h */,
+ 7261D467277A43BA00D323AC /* UnityNativeModule.m */,
0053E4872319422D0014F962 /* UnityResponderViewManager.h */,
0053E4852319420A0014F962 /* UnityResponderViewManager.m */,
0053E4842319410E0014F962 /* UnityResponderView.h */,
@@ -105,6 +115,7 @@
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
+ English,
en,
);
mainGroup = 58B511D21A9E6C8500147676;
@@ -122,9 +133,11 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ 7261D468277A43BA00D323AC /* UnityNativeModule.m in Sources */,
B3E7B58A1CC2AC0600A0062D /* RNUnity.m in Sources */,
0053E4862319420A0014F962 /* UnityResponderViewManager.m in Sources */,
0053E483231940930014F962 /* UnityResponderView.m in Sources */,
+ 7261D46B277A43FD00D323AC /* UnityUtils.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/ios/RNUnity/UnityNativeModule.h b/ios/RNUnity/UnityNativeModule.h
new file mode 100644
index 0000000..34f3d4e
--- /dev/null
+++ b/ios/RNUnity/UnityNativeModule.h
@@ -0,0 +1,11 @@
+//
+// UnityNativeModule.h
+// RNUnity
+//
+
+#import
+#import
+#import "UnityUtils.h"
+
+@interface UnityNativeModule : NSObject
+@end
diff --git a/ios/RNUnity/UnityNativeModule.m b/ios/RNUnity/UnityNativeModule.m
new file mode 100644
index 0000000..bfe7ab7
--- /dev/null
+++ b/ios/RNUnity/UnityNativeModule.m
@@ -0,0 +1,68 @@
+//
+// UnityNativeModule.m
+// RNUnityView
+//
+
+#import "UnityNativeModule.h"
+
+@implementation UnityNativeModule
+
+@synthesize bridge = _bridge;
+
+RCT_EXPORT_MODULE(UnityNativeModule);
+
+- (id)init
+{
+ self = [super init];
+ if (self) {
+ [UnityUtils addUnityEventListener:self];
+ }
+ return self;
+}
+
+- (NSArray *)supportedEvents
+{
+ return @[@"onUnityMessage"];
+}
+
++ (BOOL)requiresMainQueueSetup
+{
+ return YES;
+}
+
+RCT_EXPORT_METHOD(isReady:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
+{
+ resolve(@([UnityUtils isUnityReady]));
+}
+
+RCT_EXPORT_METHOD(createUnity:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
+{
+ [UnityUtils createPlayer:^{
+ resolve(@(YES));
+ }];
+}
+
+RCT_EXPORT_METHOD(postMessage:(NSString *)gameObject methodName:(NSString *)methodName message:(NSString *)message)
+{
+ UnityPostMessage(gameObject, methodName, message);
+}
+
+RCT_EXPORT_METHOD(pause)
+{
+ UnityPauseCommand();
+}
+
+RCT_EXPORT_METHOD(resume)
+{
+ UnityResumeCommand();
+}
+
+- (void)onMessage:(NSString *)message {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+ [_bridge.eventDispatcher sendDeviceEventWithName:@"onUnityMessage"
+ body:message];
+#pragma clang diagnostic pop
+}
+
+@end
diff --git a/ios/RNUnity/UnityUtils.h b/ios/RNUnity/UnityUtils.h
new file mode 100644
index 0000000..d6a33d6
--- /dev/null
+++ b/ios/RNUnity/UnityUtils.h
@@ -0,0 +1,39 @@
+#import
+
+#ifndef UnityUtils_h
+#define UnityUtils_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void InitArgs(int argc, char* argv[]);
+
+bool UnityIsInited(void);
+
+void InitUnity();
+
+void UnityPostMessage(NSString* gameObject, NSString* methodName, NSString* message);
+
+void UnityPauseCommand();
+
+void UnityResumeCommand();
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+@protocol UnityEventListener
+- (void)onMessage:(NSString *)message;
+@end
+
+@interface UnityUtils : NSObject
+
++ (BOOL)isUnityReady;
++ (void)createPlayer:(void (^)(void))completed;
++ (void)addUnityEventListener:(id)listener;
++ (void)removeUnityEventListener:(id)listener;
+
+@end
+
+#endif /* UnityUtils_h */
diff --git a/ios/RNUnity/UnityUtils.mm b/ios/RNUnity/UnityUtils.mm
new file mode 100644
index 0000000..ee1c2ad
--- /dev/null
+++ b/ios/RNUnity/UnityUtils.mm
@@ -0,0 +1,176 @@
+#include "RegisterMonoModules.h"
+#include "RegisterFeatures.h"
+#include
+#import
+#import "UnityInterface.h"
+#import "UnityUtils.h"
+#import "UnityAppController.h"
+
+// Hack to work around iOS SDK 4.3 linker problem
+// we need at least one __TEXT, __const section entry in main application .o files
+// to get this section emitted at right time and so avoid LC_ENCRYPTION_INFO size miscalculation
+static const int constsection = 0;
+
+bool unity_inited = false;
+
+int g_argc;
+char** g_argv;
+
+void UnityInitTrampoline();
+
+extern "C" void InitArgs(int argc, char* argv[])
+{
+ g_argc = argc;
+ g_argv = argv;
+}
+
+extern "C" bool UnityIsInited()
+{
+ return unity_inited;
+}
+
+extern "C" void InitUnity()
+{
+ if (unity_inited) {
+ return;
+ }
+ unity_inited = true;
+
+ UnityInitStartupTime();
+
+ @autoreleasepool
+ {
+ UnityInitTrampoline();
+ UnityInitRuntime(g_argc, g_argv);
+
+ RegisterMonoModules();
+ NSLog(@"-> registered mono modules %p\n", &constsection);
+ 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);
+ }
+}
+
+extern "C" void UnityPostMessage(NSString* gameObject, NSString* methodName, NSString* message)
+{
+ UnitySendMessage([gameObject UTF8String], [methodName UTF8String], [message UTF8String]);
+}
+
+extern "C" void UnityPauseCommand()
+{
+ dispatch_async(dispatch_get_main_queue(), ^{
+ UnityPause(1);
+ });
+}
+
+extern "C" void UnityResumeCommand()
+{
+ dispatch_async(dispatch_get_main_queue(), ^{
+ UnityPause(0);
+ });
+}
+
+@implementation UnityUtils
+
+static NSHashTable* mUnityEventListeners = [NSHashTable weakObjectsHashTable];
+static BOOL _isUnityReady = NO;
+
++ (BOOL)isUnityReady
+{
+ return _isUnityReady;
+}
+
++ (void)handleAppStateDidChange:(NSNotification *)notification
+{
+ if (!_isUnityReady) {
+ return;
+ }
+ UnityAppController* unityAppController = GetAppController();
+
+ UIApplication* application = [UIApplication sharedApplication];
+
+ if ([notification.name isEqualToString:UIApplicationWillResignActiveNotification]) {
+ [unityAppController applicationWillResignActive:application];
+ } else if ([notification.name isEqualToString:UIApplicationDidEnterBackgroundNotification]) {
+ [unityAppController applicationDidEnterBackground:application];
+ } else if ([notification.name isEqualToString:UIApplicationWillEnterForegroundNotification]) {
+ [unityAppController applicationWillEnterForeground:application];
+ } else if ([notification.name isEqualToString:UIApplicationDidBecomeActiveNotification]) {
+ [unityAppController applicationDidBecomeActive:application];
+ } else if ([notification.name isEqualToString:UIApplicationWillTerminateNotification]) {
+ [unityAppController applicationWillTerminate:application];
+ } else if ([notification.name isEqualToString:UIApplicationDidReceiveMemoryWarningNotification]) {
+ [unityAppController applicationDidReceiveMemoryWarning:application];
+ }
+}
+
++ (void)listenAppState
+{
+ for (NSString *name in @[UIApplicationDidBecomeActiveNotification,
+ UIApplicationDidEnterBackgroundNotification,
+ UIApplicationWillTerminateNotification,
+ UIApplicationWillResignActiveNotification,
+ UIApplicationWillEnterForegroundNotification,
+ UIApplicationDidReceiveMemoryWarningNotification]) {
+
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(handleAppStateDidChange:)
+ name:name
+ object:nil];
+ }
+}
+
++ (void)createPlayer:(void (^)(void))completed
+{
+ if (_isUnityReady) {
+ completed();
+ return;
+ }
+
+ [[NSNotificationCenter defaultCenter] addObserverForName:@"UnityReady" object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
+ _isUnityReady = YES;
+ completed();
+ }];
+
+ if (UnityIsInited()) {
+ return;
+ }
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ UIApplication* application = [UIApplication sharedApplication];
+
+ // Always keep RN window in top
+ application.keyWindow.windowLevel = UIWindowLevelNormal + 1;
+
+ InitUnity();
+
+ UnityAppController *controller = GetAppController();
+ [controller application:application didFinishLaunchingWithOptions:nil];
+ [controller applicationDidBecomeActive:application];
+
+ [UnityUtils listenAppState];
+ });
+}
+
+extern "C" void onUnityMessage(const char* message)
+{
+ for (id listener in mUnityEventListeners) {
+ [listener onMessage:[NSString stringWithUTF8String:message]];
+ }
+}
+
++ (void)addUnityEventListener:(id)listener
+{
+ [mUnityEventListeners addObject:listener];
+}
+
++ (void)removeUnityEventListener:(id)listener
+{
+ [mUnityEventListeners removeObject:listener];
+}
+
+@end
diff --git a/package.json b/package.json
index 6a1e10b..c570122 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "react-native-unity-play",
- "version": "0.1.6",
+ "version": "0.1.7",
"description": "React Native package to use Unity as library with React Native app",
"main": "index.js",
"scripts": {