├── .gitattributes ├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── android ├── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── no │ └── asmadsen │ └── unity │ └── view │ ├── UnityEventListener.java │ ├── UnityNativeModule.java │ ├── UnityUtils.java │ ├── UnityView.java │ ├── UnityViewManager.java │ └── UnityViewPackage.java ├── docs ├── android-graphics.png ├── android-player-settings.png ├── bundle-id.png ├── dead-code-stripping.png ├── ios-add-unity-project.png ├── ios-add-unityframework.png ├── ios-player-settings.png ├── ios-set-target-membership.png └── unity-build.png ├── example ├── .buckconfig ├── .eslintrc.js ├── .flowconfig ├── .gitattributes ├── .gitignore ├── .prettierrc.js ├── .watchmanconfig ├── App.js ├── __tests__ │ └── App-test.js ├── android │ ├── app │ │ ├── _BUCK │ │ ├── build.gradle │ │ ├── build_defs.bzl │ │ ├── debug.keystore │ │ ├── proguard-rules.pro │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ ├── MainActivity.java │ │ │ │ └── MainApplication.java │ │ │ └── res │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ └── values │ │ │ ├── strings.xml │ │ │ └── styles.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle ├── app.json ├── babel.config.js ├── index.js ├── ios │ ├── Podfile │ ├── Podfile.lock │ ├── example-tvOS │ │ └── Info.plist │ ├── example-tvOSTests │ │ └── Info.plist │ ├── example.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ ├── example-tvOS.xcscheme │ │ │ └── example.xcscheme │ ├── example.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── example │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Base.lproj │ │ │ └── LaunchScreen.xib │ │ ├── Images.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Info.plist │ │ └── main.m │ └── exampleTests │ │ ├── Info.plist │ │ └── exampleTests.m ├── metro.config.js ├── package.json ├── unity │ └── example │ │ ├── .gitignore │ │ ├── Assets │ │ ├── Scenes.meta │ │ ├── Scenes │ │ │ ├── SampleScene.unity │ │ │ └── SampleScene.unity.meta │ │ ├── Scripts.meta │ │ ├── Scripts │ │ │ ├── Editor.meta │ │ │ ├── Editor │ │ │ │ ├── Build.cs │ │ │ │ ├── Build.cs.meta │ │ │ │ ├── XCodePostBuild.cs │ │ │ │ └── XCodePostBuild.cs.meta │ │ │ ├── Newtonsoft.Json.meta │ │ │ ├── Newtonsoft.Json │ │ │ │ ├── Json_net.meta │ │ │ │ └── Json_net │ │ │ │ │ ├── JsonNet.meta │ │ │ │ │ ├── JsonNet.unitypackage.json │ │ │ │ │ ├── JsonNet.unitypackage.json.meta │ │ │ │ │ └── JsonNet │ │ │ │ │ ├── Newtonsoft.Json.dll │ │ │ │ │ └── Newtonsoft.Json.dll.meta │ │ │ ├── Rotate.cs │ │ │ ├── Rotate.cs.meta │ │ │ ├── UnityMessageManager.cs │ │ │ └── UnityMessageManager.cs.meta │ │ ├── link.xml │ │ └── link.xml.meta │ │ ├── Packages │ │ └── manifest.json │ │ └── ProjectSettings │ │ ├── AudioManager.asset │ │ ├── ClusterInputManager.asset │ │ ├── DynamicsManager.asset │ │ ├── EditorBuildSettings.asset │ │ ├── EditorSettings.asset │ │ ├── GraphicsSettings.asset │ │ ├── InputManager.asset │ │ ├── NavMeshAreas.asset │ │ ├── Physics2DSettings.asset │ │ ├── PresetManager.asset │ │ ├── ProjectSettings.asset │ │ ├── ProjectVersion.txt │ │ ├── QualitySettings.asset │ │ ├── TagManager.asset │ │ ├── TimeManager.asset │ │ ├── UnityConnectSettings.asset │ │ ├── VFXManager.asset │ │ └── XRSettings.asset └── yarn.lock ├── ios ├── .gitignore ├── RNUnityView.h ├── RNUnityView.m ├── RNUnityViewManager.h ├── RNUnityViewManager.m ├── UnityNativeModule.h ├── UnityNativeModule.m ├── UnityUtils.h ├── UnityUtils.mm ├── UnityView.xcodeproj │ └── project.pbxproj └── UnityView.xcworkspace │ └── contents.xcworkspacedata ├── package.json ├── react-native-unity-view.podspec ├── scripts └── examples_postinstall.js ├── src ├── MessageHandler.ts ├── UnityModule.ts ├── UnityView.tsx └── index.ts ├── template ├── Assets │ ├── Scripts │ │ ├── Newtonsoft.Json │ │ │ └── Json_net │ │ │ │ ├── JsonNet.unitypackage.json │ │ │ │ └── JsonNet │ │ │ │ ├── Newtonsoft.Json.dll │ │ │ │ └── Newtonsoft.Json.dll.mdb │ │ └── UnityMessageManager.cs │ └── link.xml ├── Build.cs └── XCodePostBuild.cs ├── tsconfig.json └── yarn.lock /.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /dist/ 2 | 3 | 4 | 5 | # Created by https://www.gitignore.io/api/linux,xcode,macos,windows,reactnative,intellij+all 6 | # Edit at https://www.gitignore.io/?templates=linux,xcode,macos,windows,reactnative,intellij+all 7 | 8 | ### Intellij+all ### 9 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 10 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 11 | 12 | # User-specific stuff 13 | .idea/**/workspace.xml 14 | .idea/**/tasks.xml 15 | .idea/**/usage.statistics.xml 16 | .idea/**/dictionaries 17 | .idea/**/shelf 18 | 19 | # Generated files 20 | .idea/**/contentModel.xml 21 | 22 | # Sensitive or high-churn files 23 | .idea/**/dataSources/ 24 | .idea/**/dataSources.ids 25 | .idea/**/dataSources.local.xml 26 | .idea/**/sqlDataSources.xml 27 | .idea/**/dynamic.xml 28 | .idea/**/uiDesigner.xml 29 | .idea/**/dbnavigator.xml 30 | 31 | # Gradle 32 | .idea/**/gradle.xml 33 | .idea/**/libraries 34 | 35 | # Gradle and Maven with auto-import 36 | # When using Gradle or Maven with auto-import, you should exclude module files, 37 | # since they will be recreated, and may cause churn. Uncomment if using 38 | # auto-import. 39 | # .idea/modules.xml 40 | # .idea/*.iml 41 | # .idea/modules 42 | # *.iml 43 | # *.ipr 44 | 45 | # CMake 46 | cmake-build-*/ 47 | 48 | # Mongo Explorer plugin 49 | .idea/**/mongoSettings.xml 50 | 51 | # File-based project format 52 | *.iws 53 | 54 | # IntelliJ 55 | out/ 56 | 57 | # mpeltonen/sbt-idea plugin 58 | .idea_modules/ 59 | 60 | # JIRA plugin 61 | atlassian-ide-plugin.xml 62 | 63 | # Cursive Clojure plugin 64 | .idea/replstate.xml 65 | 66 | # Crashlytics plugin (for Android Studio and IntelliJ) 67 | com_crashlytics_export_strings.xml 68 | crashlytics.properties 69 | crashlytics-build.properties 70 | fabric.properties 71 | 72 | # Editor-based Rest Client 73 | .idea/httpRequests 74 | 75 | # Android studio 3.1+ serialized cache file 76 | .idea/caches/build_file_checksums.ser 77 | 78 | ### Intellij+all Patch ### 79 | # Ignores the whole .idea folder and all .iml files 80 | # See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 81 | 82 | .idea/ 83 | 84 | # Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 85 | 86 | *.iml 87 | modules.xml 88 | .idea/misc.xml 89 | *.ipr 90 | 91 | # Sonarlint plugin 92 | .idea/sonarlint 93 | 94 | ### Linux ### 95 | *~ 96 | 97 | # temporary files which can be created if a process still has a handle open of a deleted file 98 | .fuse_hidden* 99 | 100 | # KDE directory preferences 101 | .directory 102 | 103 | # Linux trash folder which might appear on any partition or disk 104 | .Trash-* 105 | 106 | # .nfs files are created when an open file is removed but is still being accessed 107 | .nfs* 108 | 109 | ### macOS ### 110 | # General 111 | .DS_Store 112 | ios/.DS_Store 113 | .AppleDouble 114 | .LSOverride 115 | 116 | # Icon must end with two \r 117 | Icon 118 | 119 | # Thumbnails 120 | ._* 121 | 122 | # Files that might appear in the root of a volume 123 | .DocumentRevisions-V100 124 | .fseventsd 125 | .Spotlight-V100 126 | .TemporaryItems 127 | .Trashes 128 | .VolumeIcon.icns 129 | .com.apple.timemachine.donotpresent 130 | 131 | # Directories potentially created on remote AFP share 132 | .AppleDB 133 | .AppleDesktop 134 | Network Trash Folder 135 | Temporary Items 136 | .apdisk 137 | 138 | ### ReactNative ### 139 | # React Native Stack Base 140 | 141 | .expo 142 | __generated__ 143 | 144 | ### ReactNative.Xcode Stack ### 145 | # Xcode 146 | # 147 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 148 | 149 | ## User settings 150 | xcuserdata/ 151 | 152 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) 153 | *.xcscmblueprint 154 | *.xccheckout 155 | 156 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) 157 | build/ 158 | DerivedData/ 159 | *.moved-aside 160 | *.pbxuser 161 | !default.pbxuser 162 | *.mode1v3 163 | !default.mode1v3 164 | *.mode2v3 165 | !default.mode2v3 166 | *.perspectivev3 167 | !default.perspectivev3 168 | 169 | ## Xcode Patch 170 | *.xcodeproj/* 171 | !*.xcodeproj/project.pbxproj 172 | !*.xcodeproj/xcshareddata/ 173 | !*.xcworkspace/contents.xcworkspacedata 174 | /*.gcno 175 | 176 | ### ReactNative.macOS Stack ### 177 | # General 178 | 179 | # Icon must end with two \r 180 | Icon 181 | 182 | 183 | # Thumbnails 184 | 185 | # Files that might appear in the root of a volume 186 | 187 | # Directories potentially created on remote AFP share 188 | 189 | ### ReactNative.Gradle Stack ### 190 | .gradle 191 | 192 | # Ignore Gradle GUI config 193 | gradle-app.setting 194 | 195 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 196 | !gradle-wrapper.jar 197 | 198 | # Cache of project 199 | .gradletasknamecache 200 | 201 | # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 202 | # gradle/wrapper/gradle-wrapper.properties 203 | 204 | ### ReactNative.Linux Stack ### 205 | 206 | # temporary files which can be created if a process still has a handle open of a deleted file 207 | 208 | # KDE directory preferences 209 | 210 | # Linux trash folder which might appear on any partition or disk 211 | 212 | # .nfs files are created when an open file is removed but is still being accessed 213 | 214 | ### ReactNative.Android Stack ### 215 | # Built application files 216 | *.apk 217 | *.ap_ 218 | *.aab 219 | 220 | # Files for the ART/Dalvik VM 221 | *.dex 222 | 223 | # Java class files 224 | *.class 225 | 226 | # Generated files 227 | bin/ 228 | gen/ 229 | release/ 230 | 231 | # Gradle files 232 | .gradle/ 233 | 234 | # Local configuration file (sdk path, etc) 235 | local.properties 236 | 237 | # Proguard folder generated by Eclipse 238 | proguard/ 239 | 240 | # Log Files 241 | *.log 242 | 243 | # Android Studio Navigation editor temp files 244 | .navigation/ 245 | 246 | # Android Studio captures folder 247 | captures/ 248 | 249 | # IntelliJ 250 | .idea/workspace.xml 251 | .idea/tasks.xml 252 | .idea/gradle.xml 253 | .idea/assetWizardSettings.xml 254 | .idea/dictionaries 255 | .idea/libraries 256 | # Android Studio 3 in .gitignore file. 257 | .idea/caches 258 | .idea/modules.xml 259 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you 260 | .idea/navEditor.xml 261 | 262 | # Keystore files 263 | # Uncomment the following lines if you do not want to check your keystore files in. 264 | #*.jks 265 | #*.keystore 266 | 267 | # External native build folder generated in Android Studio 2.2 and later 268 | .externalNativeBuild 269 | 270 | # Google Services (e.g. APIs or Firebase) 271 | # google-services.json 272 | 273 | # Freeline 274 | freeline.py 275 | freeline/ 276 | freeline_project_description.json 277 | 278 | # fastlane 279 | fastlane/report.xml 280 | fastlane/Preview.html 281 | fastlane/screenshots 282 | fastlane/test_output 283 | fastlane/readme.md 284 | 285 | # Version control 286 | vcs.xml 287 | 288 | # lint 289 | lint/intermediates/ 290 | lint/generated/ 291 | lint/outputs/ 292 | lint/tmp/ 293 | # lint/reports/ 294 | 295 | ### ReactNative.Buck Stack ### 296 | buck-out/ 297 | .buckconfig.local 298 | .buckd/ 299 | .buckversion 300 | .fakebuckversion 301 | 302 | ### ReactNative.Node Stack ### 303 | # Logs 304 | logs 305 | npm-debug.log* 306 | yarn-debug.log* 307 | yarn-error.log* 308 | lerna-debug.log* 309 | 310 | # Diagnostic reports (https://nodejs.org/api/report.html) 311 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 312 | 313 | # Runtime data 314 | pids 315 | *.pid 316 | *.seed 317 | *.pid.lock 318 | 319 | # Directory for instrumented libs generated by jscoverage/JSCover 320 | lib-cov 321 | 322 | # Coverage directory used by tools like istanbul 323 | coverage 324 | *.lcov 325 | 326 | # nyc test coverage 327 | .nyc_output 328 | 329 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 330 | .grunt 331 | 332 | # Bower dependency directory (https://bower.io/) 333 | bower_components 334 | 335 | # node-waf configuration 336 | .lock-wscript 337 | 338 | # Compiled binary addons (https://nodejs.org/api/addons.html) 339 | build/Release 340 | 341 | # Dependency directories 342 | node_modules/ 343 | jspm_packages/ 344 | 345 | # TypeScript v1 declaration files 346 | typings/ 347 | 348 | # TypeScript cache 349 | *.tsbuildinfo 350 | 351 | # Optional npm cache directory 352 | .npm 353 | 354 | # Optional eslint cache 355 | .eslintcache 356 | 357 | # Optional REPL history 358 | .node_repl_history 359 | 360 | # Output of 'npm pack' 361 | *.tgz 362 | 363 | # Yarn Integrity file 364 | .yarn-integrity 365 | 366 | # dotenv environment variables file 367 | .env 368 | .env.test 369 | 370 | # parcel-bundler cache (https://parceljs.org/) 371 | .cache 372 | 373 | # next.js build output 374 | .next 375 | 376 | # nuxt.js build output 377 | .nuxt 378 | 379 | # react / gatsby 380 | public/ 381 | 382 | # vuepress build output 383 | .vuepress/dist 384 | 385 | # Serverless directories 386 | .serverless/ 387 | 388 | # FuseBox cache 389 | .fusebox/ 390 | 391 | # DynamoDB Local files 392 | .dynamodb/ 393 | 394 | ### Windows ### 395 | # Windows thumbnail cache files 396 | Thumbs.db 397 | Thumbs.db:encryptable 398 | ehthumbs.db 399 | ehthumbs_vista.db 400 | 401 | # Dump file 402 | *.stackdump 403 | 404 | # Folder config file 405 | [Dd]esktop.ini 406 | 407 | # Recycle Bin used on file shares 408 | $RECYCLE.BIN/ 409 | 410 | # Windows Installer files 411 | *.cab 412 | *.msi 413 | *.msix 414 | *.msm 415 | *.msp 416 | 417 | # Windows shortcuts 418 | *.lnk 419 | 420 | ### Xcode ### 421 | # Xcode 422 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 423 | 424 | 425 | 426 | 427 | 428 | ### Xcode Patch ### 429 | **/xcshareddata/WorkspaceSettings.xcsettings 430 | 431 | # End of https://www.gitignore.io/api/linux,xcode,macos,windows,reactnative,intellij+all -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | example 2 | scripts 3 | docs -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 xzper 4 | Copyright (c) 2019 Andreas Storesund Madsen 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | // android/build.gradle 2 | 3 | def safeExtGet(prop, fallback) { 4 | rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback 5 | } 6 | 7 | buildscript { 8 | // The Android Gradle plugin is only required when opening the android folder stand-alone. 9 | // This avoids unnecessary downloads and potential conflicts when the library is included as a 10 | // module dependency in an application project. 11 | if (project == rootProject) { 12 | repositories { 13 | google() 14 | jcenter() 15 | } 16 | dependencies { 17 | classpath 'com.android.tools.build:gradle:3.4.1' 18 | } 19 | } 20 | } 21 | 22 | apply plugin: 'com.android.library' 23 | apply plugin: 'maven' 24 | 25 | // Matches values in recent template from React Native 0.59 / 0.60 26 | // https://github.com/facebook/react-native/blob/0.59-stable/template/android/build.gradle#L5-L9 27 | // https://github.com/facebook/react-native/blob/0.60-stable/template/android/build.gradle#L5-L9 28 | def DEFAULT_COMPILE_SDK_VERSION = 28 29 | def DEFAULT_BUILD_TOOLS_VERSION = "28.0.3" 30 | def DEFAULT_MIN_SDK_VERSION = 16 31 | def DEFAULT_TARGET_SDK_VERSION = 28 32 | 33 | android { 34 | compileSdkVersion safeExtGet('compileSdkVersion', DEFAULT_COMPILE_SDK_VERSION) 35 | buildToolsVersion safeExtGet('buildToolsVersion', DEFAULT_BUILD_TOOLS_VERSION) 36 | defaultConfig { 37 | minSdkVersion safeExtGet('minSdkVersion', DEFAULT_MIN_SDK_VERSION) 38 | targetSdkVersion safeExtGet('targetSdkVersion', DEFAULT_TARGET_SDK_VERSION) 39 | versionCode 1 40 | versionName "1.0" 41 | } 42 | lintOptions { 43 | abortOnError false 44 | } 45 | } 46 | 47 | repositories { 48 | mavenLocal() 49 | maven { 50 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 51 | url "$rootDir/../node_modules/react-native/android" 52 | } 53 | maven { 54 | // Android JSC is installed from npm 55 | url "$rootDir/../node_modules/jsc-android/dist" 56 | } 57 | google() 58 | jcenter() 59 | } 60 | 61 | dependencies { 62 | // ref: 63 | // https://github.com/facebook/react-native/blob/0.61-stable/template/android/app/build.gradle#L192 64 | //noinspection GradleDynamicVersion 65 | implementation project(':UnityExport') 66 | implementation ':unity-classes' 67 | implementation 'com.facebook.react:react-native:+' // From node_modules 68 | } 69 | 70 | def configureReactNativePom(def pom) { 71 | def packageJson = new groovy.json.JsonSlurper().parseText(file('../package.json').text) 72 | 73 | pom.project { 74 | name packageJson.title 75 | artifactId packageJson.name 76 | version = packageJson.version 77 | group = "no.asmadsen.unity.view" 78 | description packageJson.description 79 | url packageJson.repository.baseUrl 80 | 81 | licenses { 82 | license { 83 | name packageJson.license 84 | url packageJson.repository.baseUrl + '/blob/master/' + packageJson.licenseFilename 85 | distribution 'repo' 86 | } 87 | } 88 | 89 | developers { 90 | developer { 91 | id packageJson.author.username 92 | name packageJson.author.name 93 | } 94 | } 95 | } 96 | } 97 | 98 | afterEvaluate { project -> 99 | // some Gradle build hooks ref: 100 | // https://www.oreilly.com/library/view/gradle-beyond-the/9781449373801/ch03.html 101 | task androidJavadoc(type: Javadoc) { 102 | source = android.sourceSets.main.java.srcDirs 103 | classpath += files(android.bootClasspath) 104 | classpath += files(project.getConfigurations().getByName('compile').asList()) 105 | include '**/*.java' 106 | } 107 | 108 | task androidJavadocJar(type: Jar, dependsOn: androidJavadoc) { 109 | classifier = 'javadoc' 110 | from androidJavadoc.destinationDir 111 | } 112 | 113 | task androidSourcesJar(type: Jar) { 114 | classifier = 'sources' 115 | from android.sourceSets.main.java.srcDirs 116 | include '**/*.java' 117 | } 118 | 119 | android.libraryVariants.all { variant -> 120 | def name = variant.name.capitalize() 121 | task "jar${name}"(type: Jar, dependsOn: variant.javaCompile) { 122 | from variant.javaCompile.destinationDir 123 | } 124 | } 125 | 126 | artifacts { 127 | archives androidSourcesJar 128 | archives androidJavadocJar 129 | } 130 | 131 | task installArchives(type: Upload) { 132 | configuration = configurations.archives 133 | repositories.mavenDeployer { 134 | // Deploy to react-native-event-bridge/maven, ready to publish to npm 135 | repository url: "file://${projectDir}/../android/maven" 136 | configureReactNativePom pom 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asmadsen/react-native-unity-view/068f842716991bd0e710abae7ed6884c337ffc39/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Oct 28 12:09:53 CET 2019 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip 7 | -------------------------------------------------------------------------------- /android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /android/src/main/java/no/asmadsen/unity/view/UnityEventListener.java: -------------------------------------------------------------------------------- 1 | package no.asmadsen.unity.view; 2 | 3 | public interface UnityEventListener { 4 | void onMessage(String message); 5 | } 6 | -------------------------------------------------------------------------------- /android/src/main/java/no/asmadsen/unity/view/UnityNativeModule.java: -------------------------------------------------------------------------------- 1 | package no.asmadsen.unity.view; 2 | 3 | import com.facebook.react.bridge.Promise; 4 | import com.facebook.react.bridge.ReactApplicationContext; 5 | import com.facebook.react.bridge.ReactContext; 6 | import com.facebook.react.bridge.ReactContextBaseJavaModule; 7 | import com.facebook.react.bridge.ReactMethod; 8 | import com.facebook.react.modules.core.DeviceEventManagerModule; 9 | 10 | public class UnityNativeModule extends ReactContextBaseJavaModule implements UnityEventListener { 11 | 12 | public UnityNativeModule(ReactApplicationContext reactContext) { 13 | super(reactContext); 14 | UnityUtils.addUnityEventListener(this); 15 | } 16 | 17 | @Override 18 | public String getName() { 19 | return "UnityNativeModule"; 20 | } 21 | 22 | 23 | @ReactMethod 24 | public void isReady(Promise promise) { 25 | promise.resolve(UnityUtils.isUnityReady()); 26 | } 27 | 28 | @ReactMethod 29 | public void createUnity(final Promise promise) { 30 | UnityUtils.createPlayer(getCurrentActivity(), new UnityUtils.CreateCallback() { 31 | @Override 32 | public void onReady() { 33 | promise.resolve(true); 34 | } 35 | }); 36 | } 37 | 38 | @ReactMethod 39 | public void postMessage(String gameObject, String methodName, String message) { 40 | UnityUtils.postMessage(gameObject, methodName, message); 41 | } 42 | 43 | @ReactMethod 44 | public void pause() { 45 | UnityUtils.pause(); 46 | } 47 | 48 | @ReactMethod 49 | public void resume() { 50 | UnityUtils.resume(); 51 | } 52 | 53 | @Override 54 | public void onMessage(String message) { 55 | ReactContext context = getReactApplicationContext(); 56 | context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("onUnityMessage", message); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /android/src/main/java/no/asmadsen/unity/view/UnityUtils.java: -------------------------------------------------------------------------------- 1 | package no.asmadsen.unity.view; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.graphics.PixelFormat; 6 | import android.os.Build; 7 | import android.view.ViewGroup; 8 | import android.view.WindowManager; 9 | import com.unity3d.player.UnityPlayer; 10 | import java.util.concurrent.CopyOnWriteArraySet; 11 | 12 | import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; 13 | 14 | public class UnityUtils { 15 | private static final CopyOnWriteArraySet mUnityEventListeners = 16 | new CopyOnWriteArraySet<>(); 17 | private static UnityPlayer unityPlayer; 18 | private static boolean _isUnityReady; 19 | private static boolean _isUnityPaused; 20 | 21 | public static UnityPlayer getPlayer() { 22 | if (!_isUnityReady) { 23 | return null; 24 | } 25 | return unityPlayer; 26 | } 27 | 28 | public static boolean isUnityReady() { 29 | return _isUnityReady; 30 | } 31 | 32 | public static boolean isUnityPaused() { 33 | return _isUnityPaused; 34 | } 35 | 36 | public static void createPlayer(final Activity activity, final CreateCallback callback) { 37 | if (unityPlayer != null) { 38 | callback.onReady(); 39 | return; 40 | } 41 | activity.runOnUiThread(new Runnable() { 42 | @Override 43 | public void run() { 44 | activity.getWindow().setFormat(PixelFormat.RGBA_8888); 45 | int flag = activity.getWindow().getAttributes().flags; 46 | boolean fullScreen = false; 47 | if ((flag & WindowManager.LayoutParams.FLAG_FULLSCREEN) == WindowManager.LayoutParams.FLAG_FULLSCREEN) { 48 | fullScreen = true; 49 | } 50 | 51 | unityPlayer = new UnityPlayer(activity); 52 | 53 | try { 54 | // wait a moument. fix unity cannot start when startup. 55 | Thread.sleep(1000); 56 | } catch (Exception e) { 57 | } 58 | 59 | // start unity 60 | addUnityViewToBackground(); 61 | unityPlayer.windowFocusChanged(true); 62 | unityPlayer.requestFocus(); 63 | unityPlayer.resume(); 64 | 65 | // restore window layout 66 | if (!fullScreen) { 67 | activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); 68 | activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); 69 | } 70 | _isUnityReady = true; 71 | callback.onReady(); 72 | } 73 | }); 74 | } 75 | 76 | public static void postMessage(String gameObject, String methodName, String message) { 77 | if (!_isUnityReady) { 78 | return; 79 | } 80 | UnityPlayer.UnitySendMessage(gameObject, methodName, message); 81 | } 82 | 83 | public static void pause() { 84 | if (unityPlayer != null) { 85 | unityPlayer.pause(); 86 | _isUnityPaused = true; 87 | } 88 | } 89 | 90 | public static void resume() { 91 | if (unityPlayer != null) { 92 | unityPlayer.resume(); 93 | _isUnityPaused = false; 94 | } 95 | } 96 | 97 | /** 98 | * Invoke by unity C# 99 | */ 100 | public static void onUnityMessage(String message) { 101 | for (UnityEventListener listener : mUnityEventListeners) { 102 | try { 103 | listener.onMessage(message); 104 | } catch (Exception e) { 105 | } 106 | } 107 | } 108 | 109 | public static void addUnityEventListener(UnityEventListener listener) { 110 | mUnityEventListeners.add(listener); 111 | } 112 | 113 | public static void removeUnityEventListener(UnityEventListener listener) { 114 | mUnityEventListeners.remove(listener); 115 | } 116 | 117 | public static void addUnityViewToBackground() { 118 | if (unityPlayer == null) { 119 | return; 120 | } 121 | if (unityPlayer.getParent() != null) { 122 | ((ViewGroup) unityPlayer.getParent()).removeView(unityPlayer); 123 | } 124 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 125 | unityPlayer.setZ(-1f); 126 | } 127 | final Activity activity = ((Activity) unityPlayer.getContext()); 128 | ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(1, 1); 129 | activity.addContentView(unityPlayer, layoutParams); 130 | } 131 | 132 | public static void addUnityViewToGroup(ViewGroup group) { 133 | if (unityPlayer == null) { 134 | return; 135 | } 136 | if (unityPlayer.getParent() != null) { 137 | ((ViewGroup) unityPlayer.getParent()).removeView(unityPlayer); 138 | } 139 | ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT); 140 | group.addView(unityPlayer, 0, layoutParams); 141 | unityPlayer.windowFocusChanged(true); 142 | unityPlayer.requestFocus(); 143 | unityPlayer.resume(); 144 | } 145 | 146 | public interface CreateCallback { 147 | void onReady(); 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /android/src/main/java/no/asmadsen/unity/view/UnityView.java: -------------------------------------------------------------------------------- 1 | package no.asmadsen.unity.view; 2 | 3 | import android.content.Context; 4 | import android.content.res.Configuration; 5 | import android.widget.FrameLayout; 6 | import com.unity3d.player.UnityPlayer; 7 | 8 | public class UnityView extends FrameLayout { 9 | 10 | private UnityPlayer view; 11 | 12 | protected UnityView(Context context) { 13 | super(context); 14 | } 15 | 16 | public void setUnityPlayer(UnityPlayer player) { 17 | this.view = player; 18 | UnityUtils.addUnityViewToGroup(this); 19 | } 20 | 21 | @Override 22 | public void onWindowFocusChanged(boolean hasWindowFocus) { 23 | super.onWindowFocusChanged(hasWindowFocus); 24 | if (view != null) { 25 | view.windowFocusChanged(hasWindowFocus); 26 | } 27 | } 28 | 29 | @Override 30 | protected void onConfigurationChanged(Configuration newConfig) { 31 | super.onConfigurationChanged(newConfig); 32 | if (view != null) { 33 | view.configurationChanged(newConfig); 34 | } 35 | } 36 | 37 | @Override 38 | protected void onDetachedFromWindow() { 39 | UnityUtils.addUnityViewToBackground(); 40 | super.onDetachedFromWindow(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /android/src/main/java/no/asmadsen/unity/view/UnityViewManager.java: -------------------------------------------------------------------------------- 1 | package no.asmadsen.unity.view; 2 | 3 | import android.os.Handler; 4 | import android.view.View; 5 | import com.facebook.react.bridge.LifecycleEventListener; 6 | import com.facebook.react.bridge.ReactApplicationContext; 7 | import com.facebook.react.uimanager.SimpleViewManager; 8 | import com.facebook.react.uimanager.ThemedReactContext; 9 | import java.util.Map; 10 | import javax.annotation.Nullable; 11 | 12 | public class UnityViewManager extends SimpleViewManager 13 | implements LifecycleEventListener, View.OnAttachStateChangeListener { 14 | private static final String REACT_CLASS = "RNUnityView"; 15 | 16 | private ReactApplicationContext context; 17 | 18 | UnityViewManager(ReactApplicationContext context) { 19 | super(); 20 | this.context = context; 21 | context.addLifecycleEventListener(this); 22 | } 23 | 24 | @Override 25 | public String getName() { 26 | return REACT_CLASS; 27 | } 28 | 29 | @Override 30 | protected UnityView createViewInstance(ThemedReactContext reactContext) { 31 | final UnityView view = new UnityView(reactContext); 32 | view.addOnAttachStateChangeListener(this); 33 | 34 | if (UnityUtils.getPlayer() != null) { 35 | view.setUnityPlayer(UnityUtils.getPlayer()); 36 | } else { 37 | UnityUtils.createPlayer(context.getCurrentActivity(), new UnityUtils.CreateCallback() { 38 | @Override 39 | public void onReady() { 40 | view.setUnityPlayer(UnityUtils.getPlayer()); 41 | } 42 | }); 43 | } 44 | return view; 45 | } 46 | 47 | @Override 48 | public void onDropViewInstance(UnityView view) { 49 | view.removeOnAttachStateChangeListener(this); 50 | super.onDropViewInstance(view); 51 | } 52 | 53 | @Override 54 | public void onHostResume() { 55 | if (UnityUtils.isUnityReady()) { 56 | UnityUtils.getPlayer().resume(); 57 | restoreUnityUserState(); 58 | } 59 | } 60 | 61 | @Override 62 | public void onHostPause() { 63 | if (UnityUtils.isUnityReady()) { 64 | // Don't use UnityUtils.pause() 65 | UnityUtils.getPlayer().pause(); 66 | } 67 | } 68 | 69 | @Override 70 | public void onHostDestroy() { 71 | if (UnityUtils.isUnityReady()) { 72 | UnityUtils.getPlayer().quit(); 73 | } 74 | } 75 | 76 | private void restoreUnityUserState() { 77 | // restore the unity player state 78 | if (UnityUtils.isUnityPaused()) { 79 | Handler handler = new Handler(); 80 | handler.postDelayed(new Runnable() { 81 | @Override 82 | public void run() { 83 | if (UnityUtils.getPlayer() != null) { 84 | UnityUtils.getPlayer().pause(); 85 | } 86 | } 87 | }, 300); //TODO: 300 is the right one? 88 | } 89 | } 90 | 91 | @Override 92 | public void onViewAttachedToWindow(View v) { 93 | restoreUnityUserState(); 94 | } 95 | 96 | @Override 97 | public void onViewDetachedFromWindow(View v) { 98 | 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /android/src/main/java/no/asmadsen/unity/view/UnityViewPackage.java: -------------------------------------------------------------------------------- 1 | package no.asmadsen.unity.view; 2 | 3 | import com.facebook.react.ReactPackage; 4 | import com.facebook.react.bridge.NativeModule; 5 | import com.facebook.react.bridge.ReactApplicationContext; 6 | import com.facebook.react.uimanager.ViewManager; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | public class UnityViewPackage implements ReactPackage { 12 | @Override 13 | public List createNativeModules(ReactApplicationContext reactContext) { 14 | List modules = new ArrayList<>(); 15 | modules.add(new UnityNativeModule(reactContext)); 16 | return modules; 17 | } 18 | 19 | @Override 20 | public List createViewManagers(ReactApplicationContext reactContext) { 21 | List viewManagers = new ArrayList<>(); 22 | viewManagers.add(new UnityViewManager(reactContext)); 23 | return viewManagers; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /docs/android-graphics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asmadsen/react-native-unity-view/068f842716991bd0e710abae7ed6884c337ffc39/docs/android-graphics.png -------------------------------------------------------------------------------- /docs/android-player-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asmadsen/react-native-unity-view/068f842716991bd0e710abae7ed6884c337ffc39/docs/android-player-settings.png -------------------------------------------------------------------------------- /docs/bundle-id.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asmadsen/react-native-unity-view/068f842716991bd0e710abae7ed6884c337ffc39/docs/bundle-id.png -------------------------------------------------------------------------------- /docs/dead-code-stripping.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asmadsen/react-native-unity-view/068f842716991bd0e710abae7ed6884c337ffc39/docs/dead-code-stripping.png -------------------------------------------------------------------------------- /docs/ios-add-unity-project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asmadsen/react-native-unity-view/068f842716991bd0e710abae7ed6884c337ffc39/docs/ios-add-unity-project.png -------------------------------------------------------------------------------- /docs/ios-add-unityframework.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asmadsen/react-native-unity-view/068f842716991bd0e710abae7ed6884c337ffc39/docs/ios-add-unityframework.png -------------------------------------------------------------------------------- /docs/ios-player-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asmadsen/react-native-unity-view/068f842716991bd0e710abae7ed6884c337ffc39/docs/ios-player-settings.png -------------------------------------------------------------------------------- /docs/ios-set-target-membership.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asmadsen/react-native-unity-view/068f842716991bd0e710abae7ed6884c337ffc39/docs/ios-set-target-membership.png -------------------------------------------------------------------------------- /docs/unity-build.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asmadsen/react-native-unity-view/068f842716991bd0e710abae7ed6884c337ffc39/docs/unity-build.png -------------------------------------------------------------------------------- /example/.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /example/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: '@react-native-community', 4 | }; 5 | -------------------------------------------------------------------------------- /example/.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | ; We fork some components by platform 3 | .*/*[.]android.js 4 | 5 | ; Ignore "BUCK" generated dirs 6 | /\.buckd/ 7 | 8 | ; Ignore polyfills 9 | node_modules/react-native/Libraries/polyfills/.* 10 | 11 | ; These should not be required directly 12 | ; require from fbjs/lib instead: require('fbjs/lib/warning') 13 | node_modules/warning/.* 14 | 15 | ; Flow doesn't support platforms 16 | .*/Libraries/Utilities/LoadingView.js 17 | 18 | [untyped] 19 | .*/node_modules/@react-native-community/cli/.*/.* 20 | 21 | [include] 22 | 23 | [libs] 24 | node_modules/react-native/Libraries/react-native/react-native-interface.js 25 | node_modules/react-native/flow/ 26 | 27 | [options] 28 | emoji=true 29 | 30 | esproposal.optional_chaining=enable 31 | esproposal.nullish_coalescing=enable 32 | 33 | module.file_ext=.js 34 | module.file_ext=.json 35 | module.file_ext=.ios.js 36 | 37 | munge_underscores=true 38 | 39 | module.name_mapper='^react-native$' -> '/node_modules/react-native/Libraries/react-native/react-native-implementation' 40 | module.name_mapper='^react-native/\(.*\)$' -> '/node_modules/react-native/\1' 41 | module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> '/node_modules/react-native/Libraries/Image/RelativeImageStub' 42 | 43 | suppress_type=$FlowIssue 44 | suppress_type=$FlowFixMe 45 | suppress_type=$FlowFixMeProps 46 | suppress_type=$FlowFixMeState 47 | 48 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\) 49 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\)?:? #[0-9]+ 50 | suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError 51 | 52 | [lints] 53 | sketchy-null-number=warn 54 | sketchy-null-mixed=warn 55 | sketchy-number=warn 56 | untyped-type-import=warn 57 | nonstrict-import=warn 58 | deprecated-type=warn 59 | unsafe-getters-setters=warn 60 | inexact-spread=warn 61 | unnecessary-invariant=warn 62 | signature-verification-failure=warn 63 | deprecated-utility=error 64 | 65 | [strict] 66 | deprecated-type 67 | nonstrict-import 68 | sketchy-null 69 | unclear-type 70 | unsafe-getters-setters 71 | untyped-import 72 | untyped-type-import 73 | 74 | [version] 75 | ^0.105.0 76 | -------------------------------------------------------------------------------- /example/.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | 24 | # Android/IntelliJ 25 | # 26 | build/ 27 | .idea 28 | .gradle 29 | local.properties 30 | *.iml 31 | 32 | # node.js 33 | # 34 | node_modules/ 35 | npm-debug.log 36 | yarn-error.log 37 | 38 | # BUCK 39 | buck-out/ 40 | \.buckd/ 41 | *.keystore 42 | !debug.keystore 43 | 44 | # fastlane 45 | # 46 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 47 | # screenshots whenever they are needed. 48 | # For more information about the recommended setup visit: 49 | # https://docs.fastlane.tools/best-practices/source-control/ 50 | 51 | */fastlane/report.xml 52 | */fastlane/Preview.html 53 | */fastlane/screenshots 54 | 55 | # Bundle artifact 56 | *.jsbundle 57 | 58 | # CocoaPods 59 | /ios/Pods/ 60 | 61 | 62 | ios/UnityExport 63 | android/UnityExport -------------------------------------------------------------------------------- /example/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | bracketSpacing: false, 3 | jsxBracketSameLine: true, 4 | singleQuote: true, 5 | trailingComma: 'all', 6 | }; 7 | -------------------------------------------------------------------------------- /example/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /example/App.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Sample React Native App 3 | * https://github.com/facebook/react-native 4 | * 5 | * @format 6 | * @flow 7 | */ 8 | 9 | import React, { useState } from 'react'; 10 | import { 11 | SafeAreaView, 12 | StyleSheet, 13 | ScrollView, 14 | View, 15 | Text, 16 | StatusBar, 17 | Button, 18 | Alert 19 | } from 'react-native'; 20 | 21 | import { 22 | Header, 23 | LearnMoreLinks, 24 | Colors, 25 | DebugInstructions, 26 | ReloadInstructions, 27 | } from 'react-native/Libraries/NewAppScreen'; 28 | import UnityView, { UnityModule } from '@asmadsen/react-native-unity-view'; 29 | 30 | const App: () => React$Node = () => { 31 | const [count, setClickCount] = useState(0) 32 | console.log(count) 33 | const onUnityMessage = (hander) => { 34 | console.log({hander}) 35 | } 36 | 37 | const onClick = () => { 38 | UnityModule.postMessageToUnityManager({ 39 | name: 'ToggleRotate', 40 | data: '', 41 | callBack: (data) => { 42 | Alert.alert('Tip', JSON.stringify(data)) 43 | } 44 | }); 45 | } 46 | 47 | 48 | return ( 49 | 50 | 51 | 56 | 57 |