-1

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?

OnWheel error

getBoundingClientRect error

2 Answers2

1

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.

DevAddict
  • 1,583
  • 1
  • 10
  • 17
0

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

Wasif Ali
  • 204
  • 1
  • 10