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

Component methods not passed from C# to globals #28

Closed
amagee opened this issue Sep 4, 2021 · 5 comments
Closed

Component methods not passed from C# to globals #28

amagee opened this issue Sep 4, 2021 · 5 comments
Labels
bug Something isn't working

Comments

@amagee
Copy link

amagee commented Sep 4, 2021

Turns out that whether a method on an object gets passed from C# to Javascript via the globals mechanism depends on what the object's class is.

In particular, methods on a MonoBehaviour object are not passed through, though equivalent methods on a class that derives directly from UnityEngine.Object are passed through. I initially thought it was simply a matter of the object needing to be a UnityEngine.Object, but MonoBehaviour also derives from UnityEngine.Object so it's not just that.

Not sure if this is a React Unity issue or just an issue of MonoBehaviour doing something unexpected.

Example:

// C#:

class MyComponent : MonoBehaviour {
    public void SetupStuff() {
        var component = GameObject.Find("SomeObject").GetComponent<ReactUnity.UGUI.ReactUnityUGUI>();

        // Make the component available as myComponent. The FromReact method is not available.
        component.Globals["myComponent"] = this;

        // Make a MyObject available as myObject. The FromReact method on this object is available,
        // even though it's basically the same.
        component.Globals["myObject"] = new MyObject();
    }
        
    public void FromReact(string s) {
        Debug.Log("From react (but nope) " + s);
    }
}

class MyObject : UnityEngine.Object {
    public void FromReact(string s) {
        Debug.Log("From react (and yes!) " + s);
    }
}

React:

function MyComponent() {
  const globals = globalsWatcher.useContext();
  console.log("myComponent " + (globals.myComponent.FromReact != null));
  console.log("myObject" + (globals.myObject.FromReact != null));
}

The logs will say

myComponent false
myObject true
@KurtGokhan
Copy link
Member

I am not sure but I think your classes need to be public. Otherwise none of the methods should be passed to the Javascript side.

@amagee
Copy link
Author

amagee commented Sep 5, 2021

Hm no I don't think that's right. In my example the MyObject class is not public but it still works. And if I make the MyComponent class public it still doesn't work.

@KurtGokhan
Copy link
Member

Non-public classes and methods may work in Jint but they will definitely fail in ClearScript so I recommend you make them public.

Here is the test covering this case. It seems to work in Build/Editor, ClearScript/Jint and all platforms.
https://github.com/ReactUnity/core/blob/main/Tests/Runtime/Base/InteropTests.cs

Let me know if there is any difference in your code and what I am testing, or something else that may be causing the problem.

@amagee
Copy link
Author

amagee commented Sep 7, 2021

Ok this also appears to be working now. It didn't work immediately so there still might be some issue remaining but it could have just been me doing something silly. In any case I can't reproduce the problem anymore. I'll keep an eye on it.

@KurtGokhan KurtGokhan added bug Something isn't working and removed cannot reproduce labels Sep 7, 2021
@KurtGokhan
Copy link
Member

Don't forget that the changes on Globals can still take at least 1 frame to update on React side. The way to prevent that is by doing the changes before React first renders.

Closing this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants