How to use UnityPlayer in Android Compose
In my company, I have to use 3D avatar animation using UnityPlayer derived from Unity module.
The base code I will use is consist of Android Compose.
So, I want to use UnityPlayer with Android Compose.
However, There were no information about using UnityPlayer with Compose.
This is why I write this post.
☝I introduce this post on the condition that you add UnityModule.
If you not, read this post first!!
https://antwhale94.blogspot.com/2024/03/AddingUnityModuleToAndroid.html
1. Add dependency
android {
...
buildFeatures {
viewBinding true
} ...
}
dependencies {
implementation 'androidx.compose.ui:ui-viewbinding:1.6.0'
}
You should add viewBinding dependency.
And you should add "androidx.compose.ui:ui-viewbinding" to take xml into Compose.
2. MainActivity.kt
class MainActivity : ComponentActivity() {
val TAG = MainActivity::class.java.simpleName
lateinit var mUnityPlayer: UnityPlayer
@ExperimentalMaterial3Api
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mUnityPlayer = UnityPlayer(this)
val glesMode = mUnityPlayer.getSettings().getInt("gles_mode", 1)
val trueColor8888 = false
mUnityPlayer.init(glesMode, trueColor8888)
setContent {
Surface(
modifier = Modifier
.fillMaxSize()
) {
MLCChatTheme {
NavView()
}
}
}
}
override fun onDestroy() {
Log.d(TAG, "onDestroy: ")
super.onDestroy()
mUnityPlayer.quit()
}
override fun onPause() {
Log.d(TAG, "onPause: ")
super.onPause()
mUnityPlayer.pause()
}
override fun onResume() {
Log.d(TAG, "onResume: ")
super.onResume()
mUnityPlayer.resume()
}
override fun onLowMemory() {
Log.d(TAG, "onLowMemory: ")
super.onLowMemory()
mUnityPlayer.lowMemory()
}
override fun onTrimMemory(level: Int) {
Log.d(TAG, "onTrimMemory: ")
super.onTrimMemory(level)
if(level == ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL)
mUnityPlayer.lowMemory()
}
override fun onConfigurationChanged(newConfig: Configuration) {
Log.d(TAG, "onConfigurationChanged: ")
super.onConfigurationChanged(newConfig)
mUnityPlayer.configurationChanged(newConfig)
}
override fun onWindowFocusChanged(hasFocus: Boolean) {
Log.d(TAG, "onWindowFocusChanged: $hasFocus")
super.onWindowFocusChanged(hasFocus)
mUnityPlayer.windowFocusChanged(hasFocus)
}
}
fun Context.getActivity(): ComponentActivity? = when (this) {
is ComponentActivity -> this
is ContextWrapper -> baseContext.getActivity()
else -> null
}
In my experience, The UnityPlayer derived from activity only can play animation.
I don't know why, so I make UnityPlayer object in MainActivity using MainActivity context.
The lowest function getActivity is used to get MainActivity from Composable function.
3. xml layout to put UnityPlayer
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/frameLayout"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
This layout file's name is "avatar_view_layout.xml"
Obviously, you can change this file name if you want.
4. Composable function to show UnityPlayer
@Composable
fun AvatarView() {
val TAG = "AvatarView"
val localContext = LocalContext.current
Log.d(TAG, "AvatarView composition")
val unityPlayer = (localContext.getActivity() as MainActivity).mUnityPlayer //1
AndroidViewBinding(AvatarViewLayoutBinding::inflate) { //2
if(unityPlayer.parent == null) {
Log.d(TAG, "AvatarView added")
frameLayout.addView(unityPlayer.view) //3
unityPlayer.resume()
}
}
DisposableEffect(key1 = localContext) {
onDispose { //4
Log.d(TAG, "remove AvatarView")
(unityPlayer.parent as FrameLayout).removeView(unityPlayer.view)
unityPlayer.pause()
}
}
}
1 => Get UnityPlayer object using local context
2 => AndroidViewBinding to use xml in Compose
3 => Add UnityPlayer to FrameLayout and resume UnityPlayer
4 => DisposableEffect to notice when AvatarView composable leave.
You should remove UnityPlayer from framelayout and pause it to restart when recomposing.
I don't know this is good way to use UnityPlayer with Compose, but This is only way I got this.
댓글 없음:
댓글 쓰기