Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Event handler for Unity Events is global #109

Closed
stefanb2 opened this issue Aug 14, 2020 · 5 comments · May be fixed by #110
Closed

Event handler for Unity Events is global #109

stefanb2 opened this issue Aug 14, 2020 · 5 comments · May be fixed by #110
Labels
stale Inactive for too long

Comments

@stefanb2
Copy link

Describe the bug
In our application we have two Unity WebGL components, out of which max one is visible at a time. Both components share a code base, e.g. they both send the UnityEventDispatch Unity Event to pass events to the React side. After calling

this.unityContent.on('UnityEventDispatch', this.unityEventDispatch)

in the instance constructor only one of the event handlers is ever called.

To Reproduce

ReactUnityWebGL.jslib:

mergeInto(LibraryManager.library, {
  ...
  UnityEventDispatch: function(json) {
    ReactUnityWebGL.UnityEventDispatch(Pointer_stringify(json));
  },
  ...
});

WebGLBridge.cs:

...
using UnityEngine;
using System.Runtime.InteropServices;
...

public static class WebGLBridge
{
  // These are defined as JS plugins at Assets/Plugin/ReactUnityWebGL.jslib
  ...
  [DllImport("__Internal")]
  private static extern void UnityEventDispatch(string json);
  ...
  public static void SendExternalEvent(string eventName, ...)
  {
    var data = ... // create some object that .ToString() converts to JSON string
    ...
    string json = data.ToString();
    UnityEventDispatch(json);
  }
}

UnityWrapper.js (React side)

export default class UnityWrapper extends Component {
  ...
  constructor(props) {
    ...
    this.unityContent = new UnityContent(this.configPath, this.unityLoader);
    ...
    this.unityContent.on('UnityEventDispatch', this.unityEventDispatch);
    ...
  }
  ...
  unityEventDispatch = data => {
    // parse JSON, forward event to callback and so on...
  };
  ...
}

When Unity Component 1 calls WebGLBridge.SendExternalEvent() then the event handler on the UnityContent instance for the other component is called. I didn't verify this, but I think that this depends on the order of instance creation, i.e. the last created UnityContent will override the event handler for the same event of a previous UnityContent instance.

Expected behavior
When Unity Component 1 calls WebGLBridge.SendExternalEvent() then the event handler for its UnityContent instance will be called.

Desktop

  • OS: Linux
  • Browser: Chromium
  • Version: 84
  • JSON from component build output: unityVersion: "2019.3.5f1"
  • package.json: "react-unity-webgl": "^7.1.10",
@jeffreylanters
Copy link
Owner

jeffreylanters commented Aug 14, 2020

Hi Stefan, thank you for opening an issue.

The module supports running multiple instances of a Unity application. But this is a slightly different case, since you're running the same Unity application twice. When using the Unity to React communication each instance should have their own event names.

Since the JSLib file doesn't know anything about the instances of the React component. When defining an event listener in React, event listeners with the same event name will be overwritten because they indeed have to be global for the JSLib to reach them.

A quick solution would be to let your Unity application send some kind of identifier, so you can later check this identifier in order to tell which Unity application instance did send it.

I hope this helps you with your implementation.

@stefanb2
Copy link
Author

stefanb2 commented Aug 14, 2020

I guess my text may have been misleading.

We are running two separate Unity WebGL components, i.e. 2 separate builds, 2 different game objects, 2 instances of UnityContent. The only thing they share is a source code base for common code.

But if I understand your comment correctly if two components use the same Unity Event name, that one would be shared on the React side.

This behaviour should be documented IMHO.

stefanb2 added a commit to stefanb2/react-unity-webgl that referenced this issue Aug 14, 2020
- remove IUnityEvent
- add UnityEvents class
  * AddEventListener() adds a callback for an event name
  * DispatchEvent() calls all callbacks for an event name
  * errors from event handlers are ignored
  * the first event handler returning truthy aborts dispatch
- UnityContent
  * add UnityEvents class property for global events
  * only install one callback per global event name
  * add UnityEvents instance property for instance events

Fixes jeffreylanters#109
stefanb2 added a commit to stefanb2/react-unity-webgl that referenced this issue Aug 14, 2020
Events which are dispatched via triggerUnityEvents() are instance
specific events that do not need a global event handler attached to
ReactUnityWebGL object. All other event names are assumed to be global
ones.

Fixes jeffreylanters#109
@stefanb2
Copy link
Author

The proposed changes fix the issue in our project, i.e. if you have multiple UnityContent instances that register an event handler for the same event name then all event handlers will be called.

@github-actions
Copy link

This issue is stale because it has been open for 30 days with no activity.

@github-actions github-actions bot added the stale Inactive for too long label Jun 18, 2021
@github-actions
Copy link

This issue was closed because it has been inactive for 30 days since being marked as stale.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stale Inactive for too long
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants