react-unity-webgl icon indicating copy to clipboard operation
react-unity-webgl copied to clipboard

Unable to Send Message while Unity is not Instantiated.

Open heymangal opened this issue 2 years ago • 12 comments

Please avoid duplicates

Language and Compiler

Vanilla JavaScript

What environment are you using?

Local Development Server

When does your problem occur?

When the Unity App is running

What does your problem relate to?

The problem seems React related

React-Unity-WebGL Version

9.3.0

React Version

17.0.39

Unity Version

2021.5f1

What happened?

Hello team, I am sorry to say that I am facing runtime issues within react, I have been trying to solve it for some days but without success.

  1. Image 1 https://drive.google.com/file/d/1X51vftlknpMB-kGqxvlNWk8a5f8Sbzm4/view?usp=sharing

WebGL Warning Log : When Call Unity Function Using Bridge : **use-unity-context.js:121 Unable to Send Message while Unity is not Instantiated. (anonymous) @ use-unity-context.js:121**

  1. I call Unity React functions directly from Unity Listener. https://drive.google.com/file/d/1tttT2moMFzI8SN7M1LmG8zv4RNq7oI89/view?usp=share_link

3.And this function is called from the listener. And within it Unity communicates with SendMessage https://drive.google.com/file/d/1xc00kEi81-y-yA3bX0wnyWNL230fZYvg/view?usp=sharing

  function ClickedConnectVenly() 
  {
    sendMessage(
      "Persistent",
      "Loader", false
    );
  }

But I get This Message in WebGL Log Console and not Send Message Unity Function: (All The Parameters are Verified)

WebGL Warning Log : When Call Unity Function Using Bridge :
**use-unity-context.js:121 Unable to Send Message while Unity is not Instantiated.
(anonymous) @ `use-unity-context.js:121**`
  1. Calling Function From React Button https://drive.google.com/file/d/1pNFwVxxZq9_ELmniYFHDWUc91YuUUTWE/view?usp=sharing

And now , if I call this function from react button then it works fine. But if I call from unity listener, it doesn't give me function call inside unity.

I don't know if this is an issue or my coding.

Help me Please !

Reproducible test case

No response

Would you be interested in contributing a fix?

  • [X] yes, I would like to contribute a fix

heymangal avatar Dec 27 '22 05:12 heymangal

I got the same issue migrating from version 8 to 9. It looks like the problem is that while you register a listener, that listener triggers SendMessage while the Unity component is still loading, I made it work by triggering SendMessage inside a useEffect that depends on an isLoaded state that becomes true once the component has been loaded, I already had that implementation with my own hook, however, I can see that UnityContextHook has the isLoaded property, that one should work

stevenzipgen avatar Jan 11 '23 04:01 stevenzipgen

@stevenzipgen can you send me the reference and code hint on how to use UnityContextHook.

dheerajbora98 avatar Jan 11 '23 05:01 dheerajbora98

//this will throw: Unable to Send Message while Unity is not Instantiated

` const unityContext = useUnityContext( { loaderUrl: renderer.loader.js, dataUrl: renderer.data.gz, frameworkUrl: renderer.framework.js.gz, codeUrl: renderer.wasm.gz, streamingAssetsUrl: debug, });

	useEffect(() => {
		unityContext.addEventListener("AppLoaded", (params: string) => {
			unityContext.sendMessage("interface", "SetStep", JSON.stringify({
				step: StateStep.BoundaryConfig
			}));
			}
		);
	}, []);`

//Storing a state to know when the app was loaded

`const [rendererLoaded, setRendererLoaded] = useState(false);

	useEffect(() => {
	unityContext.addEventListener("AppLoaded", (params: string) => {
		setRendererLoaded(true);
			}
		);
	}, []);
	
	useEffect(() => {
		if (rendererLoaded) {
			unityContext.sendMessage("interface", "SetStep", JSON.stringify({
				step: StateStep.BoundaryConfig
			}));
		}			
	},[rendererLoaded])`

stevenzipgen avatar Jan 11 '23 20:01 stevenzipgen

This may help some other people:

We had this error prop up when we disabled the splash screen and Unity logo. We re-enabled splash screen (disabled Unity logo though), and bam --- sendMessage works again.

We're on 2022.2.1f1. Hope this helps.

KhoiFishGST avatar Mar 07 '23 10:03 KhoiFishGST

Hi there, getting this issue too - but mine is when I try to sendMessage() or addEventListener() in a component different to the main app.tsx, where my Unity build is being rendered.

Any clue as to what I'm doing wrong?

Joshvdw avatar Mar 08 '23 22:03 Joshvdw

I have the same problem. "Unable to Send Message while Unity is not Instantiated."

Unity 2021.3.23 react-unity-webgl 9.4.0

What is the correct method to call sendMessage? Is it a library error or how are we calling it? It seems that unityInstance is always null.

chismer avatar Apr 20 '23 10:04 chismer

Same issue, code looks like:

var SendUnityMessage: ((arg0: string, arg1: string, arg2: string) => void) | null = null;
  function LoadUnityApp() {
    var baseUrl = "/chat/WebGL/CamillaTest"
    var buildUrl = baseUrl + "/Build";
      
    const { unityProvider, sendMessage } = useUnityContext({
      loaderUrl: buildUrl + "/CamillaTest.loader.js",
      dataUrl: buildUrl + "/CamillaTest.data",
      frameworkUrl: buildUrl + "/CamillaTest.framework.js",
      codeUrl: buildUrl + "/CamillaTest.wasm",
      streamingAssetsUrl: baseUrl + "/StreamingAssets",
    });

    sendMessage("BrowserPipe", "OnPacket", "test");
    if(!SendUnityMessage) {
      SendUnityMessage = sendMessage;
    }
    return <Unity unityProvider={unityProvider} />;
  }

And then elsewhere:

onMessage: (packet: CustomPacket) => {
    if(SendUnityMessage) {
         SendUnityMessage('BrowserPipe', 'OnPacket', JSON.stringify(packet));
       }

Whenever I try to send a packet over to Unity I will get the warning, however the test call I make in the LoadUnityApp() does eventually work a couple of times. Very puzzling.

TheConBot avatar Aug 17 '23 21:08 TheConBot

Same problem using sendMessage from the hook.

react-unity-webgl: 9.4.2 unity: 2022.3.6f1

const {unityProvider, isLoaded, loadingProgression, addEventListener, removeEventListener, sendMessage, takeScreenshot, unload, requestFullscreen} = useUnityContext({ loaderUrl: Build/${projectName}.loader.js, dataUrl: Build/${projectName}.data, frameworkUrl: Build/${projectName}.framework.js, codeUrl: Build/${projectName}.wasm, streamingAssetsUrl: "StreamingAssets", productName: "My Product", productVersion: "1.0.0", companyName: "Developer" });

siddie avatar Sep 17 '23 10:09 siddie

I got the same issue, and I fixed the issue with this code I'm using socket.io

const { unityProvider, sendMessage, isLoaded } = useUnityContext({
// ...
});

const socketIoClientRef = useRef<null | Socket>(null);

useEffect(() => {
    if (!isLoaded) {
      return;
    }

    socketIoClientRef.current = io('/');

    socketIoClientRef.current.on(
      'some-event',
      ({ messageId, value }) => {
        if (messageId === 'some-message') {
          sendMessage('something','something',value);
        }
      },
    );

    return () => {
      socketIoClientRef.current?.disconnect();
    };
}, [isLoaded]);

pjb6510 avatar Oct 18 '23 05:10 pjb6510

isLoaded has to be added to the dependency of useEffect. And boom it will work

shubhamkes avatar Mar 13 '24 11:03 shubhamkes

i have the same issue but it works with this code

const onStop = async (recordedBlob) => {
    console.log('recordedBlob is: ', recordedBlob);
    setResult(null)
    try {
      setLoading(true);
      const formData = new FormData();
      formData.append('audioFile', recordedBlob.blob, 'audio.mp3');
      formData.append('interviewId', id);
      const response = await Api.post('ai-interview/single/talk', formData);
      setResult(response.data)
      if (isLoaded) {
        console.log("Sending");
        sendMessage("WebManager", "PlayAudio", `${VITE_API_BASE_URL}/${response?.data?.audioPath?.audioFilePath}`);
        console.log("done!");
      }
    } catch (error) {
      console.error('Error uploading audio:', error);
    } finally {
      setLoading(false);
      setChangeIcon(true)
    }
  };
  useEffect(() => {
    if (result?.audioPath?.audioFilePath && isLoaded) {
      console.log("sending");
      sendMessage("WebManager", "PlayAudio", `${VITE_API_BASE_URL}/${result?.audioPath?.audioFilePath}`);
      console.log("done!")
    }
  }, [result?.audioPath?.audioFilePath]);

OmarBayoumy01 avatar Jun 13 '24 10:06 OmarBayoumy01

i have the same issue after follow the tutorial. after a little bit of frustration, i notice in tutorial use callback with empty dependencies [], after adding isLoaded dependency its solved [isLoaded] . Here is the code :

const handleUCommand = useCallback((dat:any) => {
      sendMessage("Comsys","SetName","its work !");
  }, [isLoaded]);

so i think everything is fine, just need to double check your code called on proper state.

rizalarsal avatar Jul 24 '24 08:07 rizalarsal