Search code examples
c#androidkotlinunity-game-enginedelegates

How to pass delegates from Unity C# to a native Kotlin Android SDK?


I have a native Android library I'm integrating into Unity which require me to pass C# delegates to the native SDK. As a design decision, I'm passing functions to the native SDK to be called when various events happen. I can't figure out how to pass a delegate to the native code which defines the handlers as public variables on the class like var onMyEvent: () -> Unit = {}. How can I pass a Unity C# function to the generated setOnMyEvent method?


Solution

  • I had a hard time with this problem since I was still thinking in terms of function pointers from the iOS integration. I tried using the low level AndroidJNI functions to force the method signature and creating function pointers from delegates to no avail. However, the solution was a lot simpler than what I was thinking. After looking at the decompiled AAR, I realized that the setOnMyEvent function expected a Function0 parameter, which is an object that conforms to the kotlin.jvm.functions.Function0 interface, defined as such:

    /** A function that takes 0 arguments. */
    public interface Function0<out R> : Function<R> {
        /** Invokes the function. */
        public operator fun invoke(): R
    }
    

    Using this, it is trivial to implement using the builtin Unity AndroidJavaProxy class:

    using UnityEngine;
    // ...
    class Function0 : AndroidJavaProxy {
      private MyDelegate _callback;
      public Function0(MyDelegate callback) : base("kotlin.jvm.functions.Function0") {
        this._callback = callback;
      }
    
      public void invoke() { _callback(); }
    }
    

    In the Unity C# wrapper class all I needed to do was the following:

    public void SetOnMyEvent(MyDelegate callback) {
      _myAndroidJavaObject.Call("setOnMyEvent", new Function0(callback));
    }
    

    I hope this helps anyone running into similar issues since I couldn't find any previous references on this topic. I spent more time than I'd like to admit on this.