jeffreylanters / react-unity-webgl

React Unity WebGL provides a modern solution for embedding Unity WebGL builds in your React Application while providing advanced APIs for two way communication and interaction between Unity and React.
https://react-unity-webgl.dev
Apache License 2.0
1.7k stars 160 forks source link

Uable to send Message while Unity is not Instantiated #556

Closed mehsieh89 closed 1 month ago

mehsieh89 commented 1 month ago

Please avoid duplicates

Language and Compiler

Babel and WebPack JavaScript

What environment are you using?

Local Development Server

When does your problem occur?

When the Context is created

What does your problem relate to?

The problem seems React related

React-Unity-WebGL Version

9.5.2

React Version

18.3.1

Unity Version

2021.3.37f1

What happened?

Unable to Send Message while Unity is not Instantiated.

https://github.com/jeffreylanters/react-unity-webgl/discussions/242

Need a code example of the answer given above for children components. Implementing as is from documentation causes this issue as well.

I tried a few variations here. Removing all of the webgl_sendLoginInfo logic to just sendMessage causes the same issue. Binding the function call to a button works sometimes, but not consistent.

Outside of functional component: const unityContext = { loaderUrl: "/OverworldPC/Build/OverworldPC.loader.js", dataUrl: "/OverworldPC/Build/OverworldPC.data", frameworkUrl: "/OverworldPC/Build/OverworldPC.framework.js", codeUrl: "/OverworldPC/Build/OverworldPC.wasm", };

const { unityProvider, sendMessage, addEventListener, removeEventListener } = useUnityContext(unityContext);

const webgl_sendLoginInfo = async () => {
    let connect_sign_result = await props.personalSign();
    console.log(connect_sign_result, "signature ??")
    console.log(props.address, "props address?");
    // stringify object with walletId, signed message, and signed message hash
    let loginInfo = {
      WalletId: props.address,
      Signature: connect_sign_result,
      Message: "PREPARE FOR BATTLE!"
    }
    console.log(loginInfo);
    let json_loginInfo = JSON.stringify(loginInfo);
    console.log(json_loginInfo, "stringified loginfo object");
    JSON.stringify(loginInfo);
    // sendMessage with that data.
    sendMessage('ReactReceive', 'SendLoginInfo', json_loginInfo);
    // sendMessage('ReactReceive', 'SendLoginInfo', 'JUST A PLAIN OLD STRING');
  }

    const handleSendLoginInfo = useCallback( async () => {
    //call webgl_sendLoginInfo
    webgl_sendLoginInfo();
    console.log("info sent");
  }, []);

  useEffect(() => {
    addEventListener("BuyGems", handleTx);
    addEventListener("LoginInfoRequest", handleSendLoginInfo);
  }, []);

    return (
    <>
      <Button onClick={() => handleSendLoginInfo()} color="#FFFFFF">TESTINGGGG</Button>
      <AspectRatio className="iframe_container" maxW='100%' ratio={ isMobile ? 9 / 16 : 16 / 9}>
          <Unity id="unity-frame" unityProvider={unityProvider}/>
      </AspectRatio>
    </>
  );

as https://github.com/jeffreylanters/react-unity-webgl/discussions/242#discussioncomment-6539149 has already asked, how do we use a hook outside of a functional component. Looking for a code example of this. Thank you

Reproducible test case

No response

Would you be interested in contributing a fix?

jeffreylanters commented 1 month ago

Hi! My laptop is out of reach at the moment, so my answer might be a bit short. But I saw your mail and will try to help you.

The reaction the Unity Instance is not found is more of a react related issue rather than related to the library.

It's because your using an asynchronous function which eventually calls "sendMessage". This gives the component a change to rerender in the background thus having a chance of losing the reference to the lastert instance of the react Unity webgl hook.

It is recommended to move the code where the message is send into its own effect where the properties are placed into the dependency array so you'll always be calling the latest instance of it.

mehsieh89 commented 1 month ago

Hi!

Thank you so much for responding. Yes, it's definitely an issue with my implementation rather than the library, I was just looking to see how it should be done rather. That makes sense. I will try and move the sendMessage out to its own useEffect to fire on its own. However, I even tried not doing the asynchronous call and then sendMessage and i hit the same issue.

-Mel

On Fri, May 31, 2024 at 4:10 PM Jeffrey Lanters @.***> wrote:

Hi! My laptop is out of reach at the moment, so my answer might be a bit short. But I saw your mail and will try to help you.

The reaction the Unity Instance is not found is more of a react related issue rather than related to the library.

It's because your using an asynchronous function which eventually calls "sendMessage". This gives the component a change to rerender in the background thus having a chance of losing the reference to the lastert instance of the react Unity webgl hook.

It is recommended to move the code where the message is send into its own effect so you'll always be calling the latest instance of it.

— Reply to this email directly, view it on GitHub https://github.com/jeffreylanters/react-unity-webgl/issues/556#issuecomment-2142914019, or unsubscribe https://github.com/notifications/unsubscribe-auth/AGFHZ7HFDKJJ42WGO42UNPLZFDKKXAVCNFSM6AAAAABITLNAFCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCNBSHEYTIMBRHE . You are receiving this because you authored the thread.Message ID: @.***>

--

mehsieh89 commented 1 month ago

Wow! Moving the send to its own effect completely worked. Thank you so much! 😱😱😱

On Fri, May 31, 2024 at 4:15 PM Mel Hsieh @.***> wrote:

Hi!

Thank you so much for responding. Yes, it's definitely an issue with my implementation rather than the library, I was just looking to see how it should be done rather. That makes sense. I will try and move the sendMessage out to its own useEffect to fire on its own. However, I even tried not doing the asynchronous call and then sendMessage and i hit the same issue.

-Mel

On Fri, May 31, 2024 at 4:10 PM Jeffrey Lanters @.***> wrote:

Hi! My laptop is out of reach at the moment, so my answer might be a bit short. But I saw your mail and will try to help you.

The reaction the Unity Instance is not found is more of a react related issue rather than related to the library.

It's because your using an asynchronous function which eventually calls "sendMessage". This gives the component a change to rerender in the background thus having a chance of losing the reference to the lastert instance of the react Unity webgl hook.

It is recommended to move the code where the message is send into its own effect so you'll always be calling the latest instance of it.

— Reply to this email directly, view it on GitHub https://github.com/jeffreylanters/react-unity-webgl/issues/556#issuecomment-2142914019, or unsubscribe https://github.com/notifications/unsubscribe-auth/AGFHZ7HFDKJJ42WGO42UNPLZFDKKXAVCNFSM6AAAAABITLNAFCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCNBSHEYTIMBRHE . You are receiving this because you authored the thread.Message ID: @.***>

--

mehsieh89 commented 1 month ago

If anyone was curious what code implementation i did. I removed the sendMessage from my asynchronous function and put it into a useEffect with a listener for a flag. Then i just set the flag at the end of the asynchronous function instead.

const [readyToSend, setReadyToSend] = useState('');

const async_function = async () => {
    let  async_call = await something();

    setReadyToSend("thing to send");
  }

useEffect(() => {
    sendMessage('GameObject', 'Event', readToSend);
  }, [readyToSend])

Thanks again to Jeffrey for the very quick response. Really saved me here!