当前位置: 首页 > 知识库问答 >
问题:

Unity:从Unity调用同伴对象内的Android Kotlin函数

呼延河
2023-03-14

我是一个本地开发人员和新的Unity。我试图发挥我的优势,在Kotlin编码,然后使用我的代码作为一个插件在Unity。我遇到的一个问题是,我不知道如何引用伴生对象内部的函数。

class MyAnalytics internal constructor(
    private val MyAnalyticsConfiguration: MyAnalyticsConfiguration
) : MyAnalyticsLogger {

    .
    .
    .

    override fun logEvent(eventRequest: Event?) {
        // some code in here
    }

    companion object {

        @JvmStatic
        fun factory(
            context: Context,
            MyAnalyticsConfiguration: MyAnalyticsConfiguration = MyAnalyticsConfiguration()
        ) : MyAnalytics {
            val eventExecutor = MyWorkManager(
                workManager = WorkManager.getInstance(context.applicationContext),
                MyAnalyticsConfiguration = MyAnalyticsConfiguration
            )
            return MyAnalytics(
                MyAnalyticsConfiguration
            )
        }
    }
}
MyAnalytics.factory(
      context = requireActivity()
)

但我怎样才能在团结中也这样做呢?以下是我尝试过的。


AndroidJavaClass UnityPlayerClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject UnityPlayerActivity = UnityPlayerClass.GetStatic<AndroidJavaObject>("currentActivity");
AndroidJavaObject myAnalytics = new AndroidJavaObject("com.test.analytics.MyAnalytics");
AndroidJavaObject analyticsObject = myAnalytics.Call<AndroidJavaObject>("factory", UnityPlayerActivity); //Also tried with 'CallStatic'; no result, same error

我收到的错误是,

AndroidJavaException:java.lang.NosuchMethodError:没有具有name='factory'signature='(landroid.app.application;)ljava/lang/object;‘在Ljava.lang.Object类中;12-10 14:00:21.883 135 37 136 74 E Unity:java.lang.nosuchmethoderror:没有具有name='factory'signature='(landroid.app.application;)ljava/lang/object;‘在Ljava.lang.Object类中;12-10 14:00:21.883 135 37 136 74 E Unity:at com.unity3d.player.reflectionhelper.getmethodid(未知来源:162)12-10 14:00:21.883 135 37 136 74 E Unity:at com.unity3d.player.unityplayer.nativerender(原生方法)12-10 14:00:21.883 135 37 136 74 E Unity:at com.unity3d.player.unityplayer.Access$300(未知来源:0)12-10 14:00:21.883 135 37 136 74 E Unity:at com.unity3d.player.UnityPlayer.Access$300(未知14:00:21.883 135 37 136 74 E Unity:at android.os.handler.dispatchmessage(handler.java:103)12-10 14:00:21.883 135 37 136 74 E Unity:at android.os.looper.loop(looper.java:214)12-10 14:00:21.883 135 37 136 74 E Unity:at com.unity3d.player.unityplayer$E.run(未知来源:20)

共有1个答案

韦辰钊
2023-03-14

为了理解实现中的问题所在,实际上需要将Kotlin代码反编译为Java代码,并基于Java代码而不是Kotlin实现Unity部分。

让我们举一个Kotlin代码的简单示例,它将打印日志,仅此而已:

class MyKotlinClass(val name: String = "DEFAULT NAME") {
    fun callNormalFunc() {
        Log.d("UNITY", "callNormalFunc from Kotlin code")
    }
    companion object {
        @JvmStatic
        fun callStaticCompanionFunc(): MyKotlinClass {
            Log.d("UNITY", "callStaticCompanionFunc from Kotlin code")
            return MyKotlinClass("NEW NAME")
        }
    }
}

反编译的Java代码如下所示:

public final class MyKotlinClass {
   @NotNull
   private final String name;
   @NotNull
   public static final MyKotlinClass.Companion Companion = new MyKotlinClass.Companion((DefaultConstructorMarker)null);

   public final void callNormalFunc() {
      Log.d("UNITY", "callNormalFunc from Kotlin code");
   }

   @NotNull
   public final String getName() {
      return this.name;
   }

   public MyKotlinClass(@NotNull String name) {
      Intrinsics.checkNotNullParameter(name, "name");
      super();
      this.name = name;
   }

   // $FF: synthetic method
   public MyKotlinClass(String var1, int var2, DefaultConstructorMarker var3) {
      if ((var2 & 1) != 0) {
         var1 = "DEFAULT NAME";
      }

      this(var1);
   }

   public MyKotlinClass() {
      this((String)null, 1, (DefaultConstructorMarker)null);
   }

   @JvmStatic
   @NotNull
   public static final MyKotlinClass callStaticCompanionFunc() {
      return Companion.callStaticCompanionFunc();
   }

   public static final class Companion {
      @JvmStatic
      @NotNull
      public final MyKotlinClass callStaticCompanionFunc() {
         Log.d("UNITY", "callStaticCompanionFunc from Kotlin code");
         return new MyKotlinClass("NEW NAME");
      }

      private Companion() {
      }

      // $FF: synthetic method
      public Companion(DefaultConstructorMarker $constructor_marker) {
         this();
      }
   }
}

从反编译的代码中我们可以看到,实际上我们可以用两种方式调用标记为@jvmstatic的函数。首先直接从我们的对象,其次使用companion对象。

public class KotlinCallScript : MonoBehaviour {

    private AndroidJavaObject _object;
    private AndroidJavaClass _staticClass;
    // Start is called before the first frame update
    private void Start () {
        _object = new AndroidJavaObject ("com.hardartcore.kotlin.MyKotlinClass");
        _staticClass = new AndroidJavaClass ("com.hardartcore.kotlin.MyKotlinClass");
        var defaultName = _object.Call<string> ("getName");
        Debug.Log ("START GET DEFAUL NAME: " + defaultName);
    }

    public void CallNormalFunction () {
        _object.Call ("callNormalFunc");
    }

    public void CallStaticFunction () {
        var companionObject = _staticClass.GetStatic<AndroidJavaObject> ("Companion");
        var newName = companionObject.Call<AndroidJavaObject> ("callStaticCompanionFunc").Call<string> ("getName");
        Debug.Log ("CALL STATIC FUNCTION NEW NAME: " + newName);
    }

    public void CallSecondWay () {
        var kotlinObject = _object.CallStatic<AndroidJavaObject> ("callStaticCompanionFunc");
        var newName = kotlinObject.Call<string> ("getName");
        Debug.Log ("CALL SECOND WAY NEW NAME: " + newName);
    }

}

你会喜欢哪种方式由你决定。

我的建议是看看你的反编译Java代码,把它贴在这里,这样我们就可以理解为什么它不能工作。

 类似资料:
  • 问题内容: 因此,我正在创建一个使用Unity的Android应用…从Unity获得了一些资产捆绑,但在Unity启动之前我不知道该URL。因此,Unity需要在本机(Android)端调用一个函数来获取URL。 我已经迷路了一段时间(Unity文档非常糟糕,恕我直言)。我决定使用NDK来帮助我。没有Unity,关于我的库文件的所有工作都会解决……现在问题是在Unity中调用这些C函数。 这是我的

  • This section is your key to getting started with Unity. It will explain the Unity interface, menu items, using assets, creating scenes, and publishing builds. 本章是Unity入门的关键。讲解Untiy界面、菜单、使用资源、创建场景和编译发布

  • 更改历史 * 2018-02-25 胡小根 初始化文档 1 历史、现状和发展 1.1 历史 1.2 现状 1.3 发展 难点:预测发展方向。 2 安装和使用 2.1 安装 2.2 使用 2.3 示例 2.4 最佳实践 难点:最佳实践,超出于示例,应该归纳总结出积累的技巧。 3 同类技术对比 难点:归纳比对项 参考资料 xxx书籍 xxx博客 Unity3D手游开发实践

  • Desktop Unity content is loaded in the browser by the Unity Web Player plugin. HTML code usually does not communicate with this plugin directly but through the help of a script called UnityObject. Its

  • 任何人都可以帮助我如何解决我遇到的这个问题? *第一个脚本: *第二个脚本: 我试图让我的玩家角色使用碰撞攻击敌人,好吧,它确实有效,玩家确实会伤害敌人,但只有当敌人的盒子对撞机再次进入我的攻击时,它才会起作用。 如果敌人已经在我的攻击区域内,并附加了一个盒子碰撞2d,那么敌人不会受到伤害,这不是我想要的。 我可以将其更改为“在触发者Stay2D上”,但敌人将继续受到伤害,直到对撞机再次被禁用。想

  • unity-XCharts 是一款基于 UGUI 的数据可视化图表插件,功能强大、易用、参数可配置,支持折线图、柱状图、饼图、雷达图、散点图、热力图、仪表盘、环形图、极坐标、水位图等常见图表。 特性 内置丰富示例和模板,参数可视化配置,效果实时预览,纯代码绘制 支持折线图、柱状图、饼图、雷达图、散点图、热力图、热力图、仪表盘、环形图、极坐标、水位图等十种常见图表 支持直线图、曲线图、面积图、阶梯线