@dolami-inc/react-native-expo-unity 0.5.1 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -33,13 +33,17 @@ class ExpoUnityView(context: Context, appContext: AppContext) : ExpoView(context
|
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
if (bridge.
|
|
37
|
-
// Unity already
|
|
38
|
-
bridge.
|
|
36
|
+
if (bridge.isReady) {
|
|
37
|
+
// Unity already initialized — reparent into this container
|
|
38
|
+
bridge.reparentInto(this)
|
|
39
39
|
} else {
|
|
40
|
-
//
|
|
40
|
+
// Initialize Unity, then reparent once engine is ready.
|
|
41
|
+
// Use postDelayed to give the engine time to boot before
|
|
42
|
+
// reparenting (avoids window detach timeout).
|
|
41
43
|
bridge.initialize(activity) {
|
|
42
|
-
|
|
44
|
+
postDelayed({
|
|
45
|
+
bridge.reparentInto(this)
|
|
46
|
+
}, 3000)
|
|
43
47
|
}
|
|
44
48
|
}
|
|
45
49
|
}
|
|
@@ -47,7 +51,7 @@ class ExpoUnityView(context: Context, appContext: AppContext) : ExpoView(context
|
|
|
47
51
|
override fun onWindowFocusChanged(hasWindowFocus: Boolean) {
|
|
48
52
|
super.onWindowFocusChanged(hasWindowFocus)
|
|
49
53
|
val bridge = UnityBridge.getInstance()
|
|
50
|
-
if (!bridge.
|
|
54
|
+
if (!bridge.isReady) return
|
|
51
55
|
bridge.unityPlayer?.windowFocusChanged(hasWindowFocus)
|
|
52
56
|
}
|
|
53
57
|
|
|
@@ -57,7 +61,7 @@ class ExpoUnityView(context: Context, appContext: AppContext) : ExpoView(context
|
|
|
57
61
|
|
|
58
62
|
if (bridge.isInitialized) {
|
|
59
63
|
if (autoUnloadOnUnmount) {
|
|
60
|
-
bridge.
|
|
64
|
+
bridge.detachView()
|
|
61
65
|
bridge.unload()
|
|
62
66
|
Log.i(TAG, "Detached and unloaded (view detached)")
|
|
63
67
|
} else {
|
|
@@ -18,9 +18,9 @@ import com.unity3d.player.UnityPlayerForActivityOrService
|
|
|
18
18
|
* Singleton managing the UnityPlayer lifecycle.
|
|
19
19
|
* Android equivalent of ios/UnityBridge.mm.
|
|
20
20
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
21
|
+
* Unity 6's engine only boots when the view is in the Activity's content
|
|
22
|
+
* view hierarchy. We park the view at MATCH_PARENT behind everything (Z=-1)
|
|
23
|
+
* to let the engine start, then reparent into the React Native container.
|
|
24
24
|
*/
|
|
25
25
|
class UnityBridge private constructor() : IUnityPlayerLifecycleEvents, NativeCallProxy.MessageListener {
|
|
26
26
|
|
|
@@ -48,19 +48,18 @@ class UnityBridge private constructor() : IUnityPlayerLifecycleEvents, NativeCal
|
|
|
48
48
|
/** Tracked here (not on the Module) so it survives module recreation. */
|
|
49
49
|
var wasRunningBeforeBackground: Boolean = false
|
|
50
50
|
|
|
51
|
+
var isReady: Boolean = false
|
|
52
|
+
private set
|
|
53
|
+
|
|
51
54
|
val isInitialized: Boolean
|
|
52
55
|
get() = unityPlayer != null
|
|
53
56
|
|
|
54
|
-
/**
|
|
55
|
-
* Returns the UnityPlayer's FrameLayout for embedding.
|
|
56
|
-
* UnityPlayerForActivityOrService creates its own rendering surface internally.
|
|
57
|
-
*/
|
|
58
57
|
val unityPlayerView: FrameLayout?
|
|
59
58
|
get() = unityPlayer?.frameLayout
|
|
60
59
|
|
|
61
60
|
/**
|
|
62
|
-
* Creates the
|
|
63
|
-
*
|
|
61
|
+
* Creates the Unity player, parks it in the Activity's content view
|
|
62
|
+
* (behind everything) to let the engine start, then fires [onReady].
|
|
64
63
|
*/
|
|
65
64
|
fun initialize(activity: Activity, onReady: (() -> Unit)? = null) {
|
|
66
65
|
if (isInitialized) {
|
|
@@ -70,10 +69,8 @@ class UnityBridge private constructor() : IUnityPlayerLifecycleEvents, NativeCal
|
|
|
70
69
|
|
|
71
70
|
val runInit = Runnable {
|
|
72
71
|
try {
|
|
73
|
-
// Set RGBA_8888 format for proper rendering
|
|
74
72
|
activity.window.setFormat(PixelFormat.RGBA_8888)
|
|
75
73
|
|
|
76
|
-
// Save fullscreen state before Unity potentially changes it
|
|
77
74
|
val flags = activity.window.attributes.flags
|
|
78
75
|
val wasFullScreen = (flags and WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0
|
|
79
76
|
|
|
@@ -83,12 +80,31 @@ class UnityBridge private constructor() : IUnityPlayerLifecycleEvents, NativeCal
|
|
|
83
80
|
NativeCallProxy.registerListener(this)
|
|
84
81
|
Log.i(TAG, "Unity player created")
|
|
85
82
|
|
|
86
|
-
//
|
|
83
|
+
// Park in Activity's content view at full size but behind
|
|
84
|
+
// everything. Unity's engine only starts when the view is
|
|
85
|
+
// in the Activity's window hierarchy.
|
|
86
|
+
val frame = player.frameLayout
|
|
87
|
+
frame.z = -1f
|
|
88
|
+
activity.addContentView(frame, ViewGroup.LayoutParams(
|
|
89
|
+
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
90
|
+
ViewGroup.LayoutParams.MATCH_PARENT
|
|
91
|
+
))
|
|
92
|
+
Log.i(TAG, "Unity view parked in Activity (background)")
|
|
93
|
+
|
|
94
|
+
// Start the rendering pipeline
|
|
95
|
+
player.windowFocusChanged(true)
|
|
96
|
+
frame.requestFocus()
|
|
97
|
+
player.resume()
|
|
98
|
+
|
|
99
|
+
// Restore fullscreen state
|
|
87
100
|
if (!wasFullScreen) {
|
|
88
101
|
activity.window.addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN)
|
|
89
102
|
activity.window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
|
|
90
103
|
}
|
|
91
104
|
|
|
105
|
+
isReady = true
|
|
106
|
+
Log.i(TAG, "Unity initialized and ready")
|
|
107
|
+
|
|
92
108
|
onReady?.invoke()
|
|
93
109
|
} catch (e: Exception) {
|
|
94
110
|
Log.e(TAG, "Failed to initialize Unity", e)
|
|
@@ -103,42 +119,46 @@ class UnityBridge private constructor() : IUnityPlayerLifecycleEvents, NativeCal
|
|
|
103
119
|
}
|
|
104
120
|
|
|
105
121
|
/**
|
|
106
|
-
*
|
|
107
|
-
*
|
|
122
|
+
* Moves the Unity view from the Activity background into the given
|
|
123
|
+
* container. Called when the React Native component is ready to show Unity.
|
|
108
124
|
*/
|
|
109
|
-
fun
|
|
125
|
+
fun reparentInto(container: ViewGroup) {
|
|
110
126
|
val frame = unityPlayerView ?: run {
|
|
111
127
|
Log.w(TAG, "Unity player view not available")
|
|
112
128
|
return
|
|
113
129
|
}
|
|
114
130
|
|
|
115
|
-
// Remove from
|
|
116
|
-
(frame.parent as? ViewGroup)?.
|
|
131
|
+
// Remove from Activity's content view
|
|
132
|
+
(frame.parent as? ViewGroup)?.let { parent ->
|
|
133
|
+
parent.endViewTransition(frame)
|
|
134
|
+
parent.removeView(frame)
|
|
135
|
+
}
|
|
117
136
|
|
|
118
|
-
|
|
137
|
+
// Reset Z and add to the React Native container
|
|
138
|
+
frame.z = 0f
|
|
139
|
+
container.addView(frame, 0, FrameLayout.LayoutParams(
|
|
119
140
|
FrameLayout.LayoutParams.MATCH_PARENT,
|
|
120
141
|
FrameLayout.LayoutParams.MATCH_PARENT
|
|
121
|
-
)
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
frame.requestFocus()
|
|
130
|
-
unityPlayer?.resume()
|
|
131
|
-
Log.i(TAG, "Rendering started")
|
|
132
|
-
}
|
|
142
|
+
))
|
|
143
|
+
|
|
144
|
+
// Re-kick rendering after reparenting
|
|
145
|
+
unityPlayer?.windowFocusChanged(true)
|
|
146
|
+
frame.requestFocus()
|
|
147
|
+
unityPlayer?.resume()
|
|
148
|
+
|
|
149
|
+
Log.i(TAG, "Unity view reparented into container")
|
|
133
150
|
}
|
|
134
151
|
|
|
135
152
|
/**
|
|
136
|
-
* Detaches the Unity view from its current parent
|
|
153
|
+
* Detaches the Unity view from its current parent.
|
|
137
154
|
*/
|
|
138
|
-
fun
|
|
155
|
+
fun detachView() {
|
|
139
156
|
val frame = unityPlayerView ?: return
|
|
140
|
-
(frame.parent as? ViewGroup)?.
|
|
141
|
-
|
|
157
|
+
(frame.parent as? ViewGroup)?.let { parent ->
|
|
158
|
+
parent.endViewTransition(frame)
|
|
159
|
+
parent.removeView(frame)
|
|
160
|
+
}
|
|
161
|
+
Log.i(TAG, "Unity view detached")
|
|
142
162
|
}
|
|
143
163
|
|
|
144
164
|
fun sendMessage(gameObject: String, methodName: String, message: String) {
|
|
@@ -164,6 +184,7 @@ class UnityBridge private constructor() : IUnityPlayerLifecycleEvents, NativeCal
|
|
|
164
184
|
|
|
165
185
|
fun unload() {
|
|
166
186
|
if (!isInitialized) return
|
|
187
|
+
isReady = false
|
|
167
188
|
Log.i(TAG, "unload called")
|
|
168
189
|
val action = Runnable {
|
|
169
190
|
unityPlayer?.unload()
|
|
@@ -181,11 +202,13 @@ class UnityBridge private constructor() : IUnityPlayerLifecycleEvents, NativeCal
|
|
|
181
202
|
override fun onUnityPlayerUnloaded() {
|
|
182
203
|
Log.i(TAG, "onUnityPlayerUnloaded")
|
|
183
204
|
unityPlayer = null
|
|
205
|
+
isReady = false
|
|
184
206
|
}
|
|
185
207
|
|
|
186
208
|
override fun onUnityPlayerQuitted() {
|
|
187
209
|
Log.i(TAG, "onUnityPlayerQuitted")
|
|
188
210
|
unityPlayer = null
|
|
211
|
+
isReady = false
|
|
189
212
|
}
|
|
190
213
|
|
|
191
214
|
// NativeCallProxy.MessageListener (Unity -> RN)
|