Skip to content

Commit 6cd3dcd

Browse files
committed
first commit
0 parents  commit 6cd3dcd

File tree

137 files changed

+17985
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

137 files changed

+17985
-0
lines changed

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.pbxproj -text

.gitignore

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
2+
# Mac
3+
.DS_Store
4+
5+
# Node.js
6+
node_modules/
7+
npm-debug.log
8+
yarn-error.log
9+
*.tgz
10+
11+
# Xcode
12+
build/
13+
*.pbxuser
14+
!default.pbxuser
15+
*.mode1v3
16+
!default.mode1v3
17+
*.mode2v3
18+
!default.mode2v3
19+
*.perspectivev3
20+
!default.perspectivev3
21+
xcuserdata
22+
*.xccheckout
23+
*.moved-aside
24+
DerivedData
25+
*.hmap
26+
*.ipa
27+
*.xcuserstate
28+
project.xcworkspace
29+
30+
# Android Studio
31+
build/
32+
.idea
33+
.gradle
34+
local.properties
35+
*.iml
36+
37+
# BUCK
38+
buck-out/
39+
\.buckd/

.npmignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/example

LICENSE

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
MIT License
2+
3+
Copyright (c) 2022 Fusetools AS
4+
Copyright (c) 2021 azesmway
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.

README.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# react-native-unity2
2+
3+
[![NPM package](https://img.shields.io/npm/v/react-native-unity2.svg?style=flat-square)](https://www.npmjs.com/package/react-native-unity2)
4+
[![License: MIT](https://img.shields.io/github/license/fusetools/react-native-unity2.svg?style=flat-square)](LICENSE)
5+
6+
Embed Unity content in your React Native app!
7+
8+
* Succesfully tested with Unity 2021 (LTS) and 2020 (LTS) on Android and iOS.
9+
10+
* Includes a complete, pre-configured [Unity project](unity) and an [example app](example).
11+
12+
> This module started out as a fork of [react-native-unity-play](https://github.com/azesmway/react-native-unity-play), but is more or less rewritten with new and improved message passing (C# <=> TypeScript), fixing glitches and stability issues, and adding Swift support. That module was forked from other modules also, so kudos to all creators! 🤩
13+
14+
## Install
15+
16+
```shell
17+
npm install react-native-unity2
18+
```
19+
20+
## Usage
21+
22+
![RNUnity running on Android device](screenshot.jpg)
23+
24+
```javascript
25+
import React from "react"
26+
import { Button, View } from "react-native"
27+
import { UnityModule, UnityView } from "react-native-unity2"
28+
29+
export default function App() {
30+
return (
31+
<UnityView style={{ flex: 1, justifyContent: "flex-end" }} onMessage={onMessage}>
32+
<View style={{ flexDirection: "row", alignContent: "space-between", justifyContent: "center" }}>
33+
<Button title={"setColor"} onPress={async () => console.log(await cubeApi.setColor(randomColor()))} />
34+
<Button title={"toggleRotate"} onPress={async () => console.log(await cubeApi.toggleRotate())} />
35+
<Button title={"getAccount"} onPress={async () => console.log(await cubeApi.getAccount())} />
36+
<Button title={"fail"} onPress={async () => console.log(await cubeApi.fail())} />
37+
</View>
38+
</UnityView>
39+
)
40+
}
41+
42+
const onMessage = data => {
43+
console.log("Unity message: " + data)
44+
}
45+
46+
const cubeApi = {
47+
setColor(color) {
48+
return UnityModule.callMethod("Cube", "setColorRN", color)
49+
},
50+
51+
toggleRotate() {
52+
return UnityModule.callMethod("Cube", "toggleRotateRN")
53+
},
54+
55+
getAccount() {
56+
return UnityModule.callMethod("Cube", "getAccountRN")
57+
},
58+
59+
fail() {
60+
return UnityModule.callMethod("Cube", "failRN")
61+
},
62+
}
63+
64+
const randomColor = () => {
65+
return `#${Math.floor(Math.random() * 16777215)
66+
.toString(16)
67+
.padStart(6, "0")}`
68+
}
69+
```
70+
71+
## Documentation
72+
73+
See [getting started](docs/getting-started.md) for information on how to set up your Unity project and React Native app.
74+
75+
See the included [Unity project](unity) and [React Native app](example) for working examples.
76+
77+
See these source files for details about message passing in Unity:
78+
79+
* [`RNBridge`](unity/Assets/RNUnity/RNBridge.cs)
80+
* [`RNPromise`](unity/Assets/RNUnity/RNPromise.cs)
81+
* [Usage examples](unity/Assets/Example/SpinCube.cs)
82+
83+
## Contributing
84+
85+
Please [report an issue](https://github.com/fusetools/react-native-unity2/issues) if you encounter a problem, or [open a pull request](https://github.com/fusetools/react-native-unity2/pulls) if you make a patch.

RNUnity.podspec

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
require 'json'
2+
3+
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
4+
5+
Pod::Spec.new do |s|
6+
s.name = "RNUnity"
7+
s.version = package['version']
8+
s.summary = package['description']
9+
s.license = package['license']
10+
s.homepage = package['homepage']
11+
s.authors = package['author']
12+
s.platform = :ios, "10.0"
13+
s.source = { :git => package['repository']['url'], :tag => "master" }
14+
s.source_files = "ios/RNUnity/**/*.{h,m}"
15+
s.requires_arc = true
16+
17+
s.xcconfig = { 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) $(BUILD_ROOT)/** $(CONFIGURATION_BUILD_DIR)/../**' }
18+
19+
s.dependency "React"
20+
21+
end
22+
23+

android/build.gradle

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
def safeExtGet(prop, fallback) {
2+
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
3+
}
4+
5+
buildscript {
6+
repositories {
7+
mavenCentral()
8+
google()
9+
jcenter()
10+
}
11+
12+
dependencies {
13+
classpath 'com.android.tools.build:gradle:4.1.3'
14+
}
15+
}
16+
17+
apply plugin: 'com.android.library'
18+
19+
android {
20+
compileSdkVersion safeExtGet('compileSdkVersion', 30)
21+
buildToolsVersion safeExtGet('buildToolsVersion', '30.0.2')
22+
23+
defaultConfig {
24+
minSdkVersion safeExtGet('minSdkVersion', 21)
25+
targetSdkVersion safeExtGet('targetSdkVersion', 30)
26+
versionCode 10
27+
versionName "0.3.4"
28+
}
29+
lintOptions {
30+
abortOnError false
31+
}
32+
}
33+
34+
repositories {
35+
mavenCentral()
36+
}
37+
38+
dependencies {
39+
implementation 'com.facebook.react:react-native:+'
40+
41+
implementation project(':unityLibrary')
42+
implementation files("${project(':unityLibrary').projectDir}/libs/unity-classes.jar")
43+
}

android/src/main/AndroidManifest.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+
package="no.fuse.rnunity">
4+
5+
</manifest>
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
package no.fuse.rnunity;
2+
3+
import android.app.Activity;
4+
import android.os.Handler;
5+
import android.os.Looper;
6+
import android.util.Log;
7+
import android.view.View;
8+
import android.view.ViewGroup;
9+
import android.view.ViewParent;
10+
11+
import com.facebook.react.bridge.LifecycleEventListener;
12+
import com.facebook.react.bridge.ReactApplicationContext;
13+
import com.facebook.react.uimanager.SimpleViewManager;
14+
import com.facebook.react.uimanager.ThemedReactContext;
15+
import com.unity3d.player.IUnityPlayerLifecycleEvents;
16+
import com.unity3d.player.UnityPlayer;
17+
18+
import java.lang.reflect.InvocationTargetException;
19+
import java.lang.reflect.Method;
20+
21+
import javax.annotation.Nonnull;
22+
23+
public class RNUnityManager extends SimpleViewManager<UnityPlayer> implements LifecycleEventListener, View.OnAttachStateChangeListener, IUnityPlayerLifecycleEvents {
24+
public static final String REACT_CLASS = "UnityView";
25+
26+
public static UnityPlayer player;
27+
28+
public RNUnityManager(ReactApplicationContext reactContext) {
29+
super();
30+
reactContext.addLifecycleEventListener(this);
31+
}
32+
33+
@Nonnull
34+
@Override
35+
public String getName() {
36+
return REACT_CLASS;
37+
}
38+
39+
@Nonnull
40+
@Override
41+
protected UnityPlayer createViewInstance(@Nonnull ThemedReactContext reactContext) {
42+
Log.d("RNUnityManager", "createViewInstance");
43+
44+
final Activity activity = reactContext.getCurrentActivity();
45+
46+
if (player == null) {
47+
player = new UnityPlayer(activity, this);
48+
} else {
49+
// Force-remove parent view to avoid exceptions thrown
50+
resetPlayerParent();
51+
52+
// Restart Unity after delay to workaround a glitch
53+
// where Unity sometimes seem to stop rendering
54+
final Handler handler = new Handler(Looper.getMainLooper());
55+
handler.postDelayed(new Runnable() {
56+
@Override
57+
public void run() {
58+
activity.runOnUiThread(new Runnable() {
59+
@Override
60+
public void run() {
61+
Log.d("RNUnityManager", "Restarting Unity player");
62+
player.pause();
63+
player.resume();
64+
}
65+
});
66+
}
67+
}, 199);
68+
}
69+
70+
player.addOnAttachStateChangeListener(this);
71+
player.windowFocusChanged(true);
72+
player.requestFocus();
73+
player.resume();
74+
75+
return player;
76+
}
77+
78+
@Override
79+
public void onDropViewInstance(UnityPlayer view) {
80+
Log.d("RNUnityManager", "onDropViewInstance: " + view);
81+
82+
view.removeOnAttachStateChangeListener(this);
83+
player.pause();
84+
}
85+
86+
@Override
87+
public void onHostResume() {
88+
Log.d("RNUnityManager", "onHostResume");
89+
90+
if (player != null)
91+
player.resume();
92+
}
93+
94+
@Override
95+
public void onHostPause() {
96+
Log.d("RNUnityManager", "onHostPause");
97+
98+
if (player != null)
99+
player.pause();
100+
}
101+
102+
@Override
103+
public void onHostDestroy() {
104+
Log.d("RNUnityManager", "onHostDestroy");
105+
}
106+
107+
@Override
108+
public void onViewAttachedToWindow(View view) {
109+
Log.d("RNUnityManager", "onViewAttachedToWindow: " + view);
110+
}
111+
112+
@Override
113+
public void onViewDetachedFromWindow(View view) {
114+
Log.d("RNUnityManager", "onViewDetachedFromWindow: " + view);
115+
}
116+
117+
@Override
118+
public void onUnityPlayerUnloaded() {
119+
Log.d("RNUnityManager", "onUnityPlayerUnloaded");
120+
}
121+
122+
@Override
123+
public void onUnityPlayerQuitted() {
124+
Log.d("RNUnityManager", "onUnityPlayerQuitted");
125+
}
126+
127+
static void resetPlayerParent() {
128+
if (player.getParent() == null)
129+
return;
130+
131+
((ViewGroup) player.getParent()).removeView(player);
132+
133+
if (player.getParent() == null)
134+
return;
135+
136+
Log.d("RNUnityManager", "Using reflection to reset parent!");
137+
138+
try {
139+
Method method = View.class.getDeclaredMethod("assignParent", new Class<?>[]{ ViewParent.class });
140+
method.setAccessible(true);
141+
method.invoke(player, new Object[]{ null });
142+
method.setAccessible(false);
143+
} catch (NoSuchMethodException e) {
144+
e.printStackTrace();
145+
} catch (IllegalArgumentException e) {
146+
e.printStackTrace();
147+
} catch (IllegalAccessException e) {
148+
e.printStackTrace();
149+
} catch (InvocationTargetException e) {
150+
e.printStackTrace();
151+
}
152+
153+
if (player.getParent() == null)
154+
return;
155+
156+
Log.e("RNUnityManager", "Unable to reset parent of player " + player);
157+
}
158+
}

0 commit comments

Comments
 (0)