Skip to content
This repository was archived by the owner on Apr 13, 2022. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions ios/RNUnity.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
13 changes: 13 additions & 0 deletions ios/RNUnity/RNUnity.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand All @@ -30,6 +32,10 @@
0053E4852319420A0014F962 /* UnityResponderViewManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UnityResponderViewManager.m; sourceTree = "<group>"; };
0053E4872319422D0014F962 /* UnityResponderViewManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UnityResponderViewManager.h; sourceTree = "<group>"; };
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 = "<group>"; };
7261D467277A43BA00D323AC /* UnityNativeModule.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UnityNativeModule.m; sourceTree = "<group>"; };
7261D469277A43E800D323AC /* UnityUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UnityUtils.h; sourceTree = "<group>"; };
7261D46A277A43FD00D323AC /* UnityUtils.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = UnityUtils.mm; sourceTree = "<group>"; };
B3E7B5881CC2AC0600A0062D /* RNUnity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNUnity.h; sourceTree = "<group>"; };
B3E7B5891CC2AC0600A0062D /* RNUnity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNUnity.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
Expand All @@ -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 */,
Expand Down Expand Up @@ -105,6 +115,7 @@
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
English,
en,
);
mainGroup = 58B511D21A9E6C8500147676;
Expand All @@ -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;
};
Expand Down
11 changes: 11 additions & 0 deletions ios/RNUnity/UnityNativeModule.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//
// UnityNativeModule.h
// RNUnity
//

#import <React/RCTEventDispatcher.h>
#import <React/RCTBridgeModule.h>
#import "UnityUtils.h"

@interface UnityNativeModule : NSObject <RCTBridgeModule, UnityEventListener>
@end
68 changes: 68 additions & 0 deletions ios/RNUnity/UnityNativeModule.m
Original file line number Diff line number Diff line change
@@ -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<NSString *> *)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
39 changes: 39 additions & 0 deletions ios/RNUnity/UnityUtils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#import <Foundation/Foundation.h>

#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 <NSObject>
- (void)onMessage:(NSString *)message;
@end

@interface UnityUtils : NSObject

+ (BOOL)isUnityReady;
+ (void)createPlayer:(void (^)(void))completed;
+ (void)addUnityEventListener:(id<UnityEventListener>)listener;
+ (void)removeUnityEventListener:(id<UnityEventListener>)listener;

@end

#endif /* UnityUtils_h */
176 changes: 176 additions & 0 deletions ios/RNUnity/UnityUtils.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
#include "RegisterMonoModules.h"
#include "RegisterFeatures.h"
#include <csignal>
#import <UIKit/UIKit.h>
#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<UnityEventListener> listener in mUnityEventListeners) {
[listener onMessage:[NSString stringWithUTF8String:message]];
}
}

+ (void)addUnityEventListener:(id<UnityEventListener>)listener
{
[mUnityEventListeners addObject:listener];
}

+ (void)removeUnityEventListener:(id<UnityEventListener>)listener
{
[mUnityEventListeners removeObject:listener];
}

@end
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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": {
Expand Down