react-native-unity
react-native-unity copied to clipboard
How to reload unity instance
I have kept androidKeepPlayerMounted this false , so first time unity loads but when i navigate to any other screen and come back again to unity screen then unity does not load below is the code. Thank you for taking a look.
import { ImageBackground, StatusBar, Image, TouchableOpacity, View, TextInput, SafeAreaView, Button, } from 'react-native'; import React, {useRef, useEffect, useState} from 'react'; import Images from '../../../Styles/Images'; import styles from './Styles'; import UnityView from '@azesmway/react-native-unity'; import {useNavigation, useFocusEffect} from '@react-navigation/native'; import Styles from '../../Auth/Login/Styles'; import {Colors} from 'react-native/Libraries/NewAppScreen'; export default function FaceInteraction(props): React.JSX.Element { const {navigation} = props; const unityRef = useRef<UnityView>(null); const [message, setMessage] = useState(''); const [showTextField, setShowTextField] = useState(false); console.log(unityRef); const handleInputChange = inputValue => { setMessage(inputValue); };
const submitHandler = () => { const unityData = { name: message, age: 3, }; let jsonedData = JSON.stringify(unityData); console.log(unityData) SendData(jsonedData); }; const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)); async function SendData(data: any) { await delay(500); console.log('data is sended from react native'); unityRef.current?.postMessage('ReactToUnity', 'GetDatas', data); }
useEffect(() => { return () => { unityRef.current?.componentWillUnmount(); }; }, []);
return (
<SafeAreaView>
<View style={{backgroundColor: 'black'}}>
<UnityView
ref={unityRef}
style={{ height: 100%', width: '100%'}}
androidKeepPlayerMounted={false}
onUnityMessage={result => {
console.log('Message Here : ', result.nativeEvent.message);
let d = result.nativeEvent.message;
if (d.includes('home')) {
navigation.navigate('BottomNavigation', {screen: 'HomeTab'});
}
}}
/>
</View>
</SafeAreaView>
); }
I wanted to share a workaround for this I have implemented:
useEffect(() => {
let timeout = undefined;
if (unityVisible) {
timeout = setTimeout(() => {
// This is a hack for Android to ensure Unity is properly woken up on
// subsequent runs! We have to wait until Unity is fully enabled to
// use it
unityRef.current?.windowFocusChanged(false);
unityRef.current?.pauseUnity(true);
unityRef.current?.resumeUnity();
unityRef.current?.windowFocusChanged(true);
}, 1100); // Why 1100? This is because the ReactNativeUnity.java has a sleep of 1000 to fix a bug with Unity starting up
}
// clear the timer when component unmouts
return () => { if (timeout !== undefined) clearTimeout(timeout); }
}, [unityVisible])
My unity render looks like this:
<View style={styles.unityContainer}>
{unityVisible ?
<UnityView
ref={unityRef}
style={styles.unityView}
onUnityMessage={(result) => handleUnityMessage(result.nativeEvent.message)}
androidKeepPlayerMounted={true}
/> : null}
...
</View>
unityVisible is just a state parameter:
const [unityVisible, setUnityVisible] = useState(false);
unityView style is like
unityView: {
position: 'absolute',
height: '100%',
width: '100%',
top: 1,
bottom: 1
},
I think the key is actually pauseUnity(true) which should be called 1100ms after the Unity view has shown. It's 1100ms because in the library it waits 1000ms for some Unity start issue, so waiting 1100ms seems to be safe from my testing. By the way, my Unity project is quite large and takes a long time to load, just for some context.
And in case you were wondering, this is safe to use on iOS as well, though iOS does not have the issue!
Thanks @anothercog . I tried many solutions, but only this works:
useEffect(() => {
let timeout = undefined;
if (unityVisible) {
timeout = setTimeout(() => {
// This is a hack for Android to ensure Unity is properly woken up on
// subsequent runs! We have to wait until Unity is fully enabled to
// use it
unityRef.current?.windowFocusChanged(false);
unityRef.current?.pauseUnity(true);
unityRef.current?.resumeUnity();
unityRef.current?.windowFocusChanged(true);
}, 1100); // Why 1100? This is because the ReactNativeUnity.java has a sleep of 1000 to fix a bug with Unity starting up
}
// clear the timer when component unmouts
return () => { if (timeout !== undefined) clearTimeout(timeout); }
}, [unityVisible])
awesome @luongle-hnl