I have the following errors when using webgl with react, I've changed nothing between the two attempts, and apparently the error changes too. The error occurs when swapping page Does anyone have an idea as to what this error would be caused by?
2 Answers
The window is not available while rendering your page in next.js. to address this problem you can use a feature called dynamic import and set the option of ssr
to false. this will disable the server-side rendering for your component and you don't have to face the problem related to SSR.
Look at the example below of usage of dynamic imports:
// component.tsx
export const Component = () => {
return (
<div>
{window.attribute}
</div>
);
};
import dynamic from 'next/dynamic';
const DynamicComponent = dynamic(() => import('./component'));
const Page = () => {
return (
<div>
<DynamicComponent/>
</div>
);
};
export default Page;
Also, keep in mind is not advised to do 3d work and game making using next.js. Simply use CRA or Vite to create SPA.

- 1,583
- 1
- 10
- 17
-
not working for me – Wasif Ali Oct 26 '22 at 12:15
-
@WasifAli add `{ssr:false}` as the second option of the `dynamic` function. so it will be as follow `dynamic(() => import('./component'), {ssr: false})` – DevAddict Oct 28 '22 at 15:08
-
I did that but not worked. Anyways, then I came up with other solution and it worked. Thanks for response :) – Wasif Ali Oct 29 '22 at 19:39
I encountered the same error. Basically, it happens when you try to access/execute a process which has not refrence in your dom. So you have to wait for await unload function(). Once unity quit its insatance then you will navigate to other route. You have to wait for unity quit function.
Incase, you are rendering unity instance in modal then you need to pass unitycontext and its function from parent component. So you can pause your other process till successsfull completion of await unload function.
For instance
simModal.tsx ( parent component )
const DynamicComponent = dynamic(() => import('../sim/index'), {
ssr: false,
})
const SimModal: FC<any> = ({ simModalOpen, setSimModalOpen, raceId }) => {
const unityProviders = useUnityContext({
loaderUrl: '/Build/myunityapp.loader.js',
dataUrl: '/Build/myunityapp.data.unityweb',
frameworkUrl: '/Build/myunityapp.framework.js.unityweb',
codeUrl: '/Build/myunityapp.wasm.unityweb',
companyName: 'Nitro',
})
const handleUnityUnmounting = async () => {
await unityProviders
.unload()
.then((res) => {
console.log('res===>', res);
setSimModalOpen(false)
})
.catch((err) => console.log('err===>', err))
}
return (
<CustomModal
isOpen={simModalOpen}
setModalOpen={setSimModalOpen}
styleclass={styles.simModal}
onHide={
unityProviders?.isLoaded
? handleUnityUnmounting
: console.log('wait')
}
>
{/* <ModalHeader closeButton></ModalHeader> */}
<ModalBody>
{/* <Sim /> */}
{simModalOpen && (
<div>
<DynamicComponent
unityProviders={unityProviders}
setSimModalOpen={setSimModalOpen}
simModalOpen={simModalOpen}
raceId={raceId}
handleUnityUnmounting={handleUnityUnmounting}
/>
</div>
)}
</ModalBody>
</CustomModal>
sim.tsx ( child component where unity instance is loaded )
const Sim: FC<any> = ({ raceId, unityProviders }) => {
const [isGameStarted, setIsGameStarted] = useState(false)
const [gameFinish, setGameFinish] = useState<boolean>(false)
const images = [loading1, loading2, loading3, loading4, loading5]
const NUMBER_OF_PICTURES = 4
const [index, setIndex] = useState(0)
useEffect(() => {
const timer = setInterval(() => {
setIndex((prevIndex) =>
prevIndex == NUMBER_OF_PICTURES ? 0 : prevIndex + 1
)
}, 3000)
return () => {
clearInterval(timer)
}
}, [])
const {
unityProvider,
sendMessage,
addEventListener,
removeEventListener,
isLoaded,
loadingProgression,
} = unityProviders
const {
data: raceLeaderBoardData,
isFetching: raceLeaderBoardLoading,
refetch: fetchRaceLeaderBoard,
} = raceLeaderBoard
.list()
.useRaceLeaderBoardlistQuery({ extendedPath: `/races/${raceId}` })
const [PopulateRaceParticipants, populateRaceParticipantsData] =
raceParticipants.form().useRaceParticipantscreateMutation()
useEffect(() => {
if (raceId) {
PopulateRaceParticipants({
body: {
raceId: raceId,
},
})
}
}, [raceId])
const handleGameOver = useCallback(async (result: unknown) => {
console.log('name in handlegameover func===>', result)
setGameFinish(true)
// setTimeout(() => {
// unityProviders.unload().then((res: any) => {
// })
// }, 7000)
}, [])
useEffect(() => {
addEventListener('GameOver', handleGameOver)
addEventListener('GameStart', handleGameStart)
// addEventListener('QuitApp', handleQuitGame)
return () => {
if (unityProvider && isLoaded) {
removeEventListener('GameOver', handleGameOver)
}
}
}, [addEventListener, removeEventListener, handleGameOver, isLoaded])
useEffect(() => {
if (isLoaded) {
sendMessage(
'_SimController',
'PopulateEventLeaderBoardData',
JSON.stringify(raceLeaderBoardData?.responseData)
)
sendMessage(
'_SimController',
'PopulateRaceParticipantsData',
JSON.stringify(populateRaceParticipantsData?.data)
)
}
}, [isLoaded])
const handleGameStart = async () => {
setIsGameStarted(true)
}
return (
<>
{!isGameStarted && loadingProgression < 1 && !gameFinish && (
<div
style={{
height: '600px',
width: '1080px',
display: !isGameStarted ? 'block' : 'none',
}}
className={styles.loadingImg}
>
<Image
src={images[index]}
height={'100%'}
width={'100%'}
unoptimized={true}
/>
</div>
)}
{gameFinish && (
<div
style={{
height: '600px',
width: '1080px',
display: gameFinish ? 'block' : 'none',
}}
className={styles.loadingImg}
>
<h5 style={{ zIndex: '99', color: 'white', }} className=' py-3'>Race Results</h5>
<RaceResults raceId={raceId} />
</div>
)}
<>
<Unity
style={{
height: '600px',
width: '1080px',
display: isGameStarted && !gameFinish ? 'block' : 'none',
}}
unityProvider={unityProvider}
/>
{Math.round(loadingProgression * 100) < 100 && (
<div className={styles.loadingWrap}>
<div className={styles.percentWrap}>
<span>Loading...</span>
<span>
{Math.round(loadingProgression * 100 + 10)}%
</span>
</div>
<div className={styles.progress}>
<div
className={styles.color}
style={{ width: loadingProgression * 1080 + 50 }}
></div>
</div>
</div>
)}
</>
</>
)
}
export default Sim

- 204
- 1
- 10