团结引擎1.4/1.5与鸿蒙ArkTs的通讯方法

2025/05 25 21:05

团结引擎C#与2与ArtkTs通讯时,不得直接调用,需要在主线程中调用

以Android为例子:

var JavaClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
var JavaObject = JavaClass.GetStatic<AndroidJavaObject>("currentActivity");
JavaObject.Call("runOnUiThread", new AndroidJavaRunnable(() => {
  JavaObject.Call<AndroidJavaObject>("getWindow").Call("XXXX");
}));

在鸿蒙中,需要进行以下异步调用,否则一切都是错的。

团结引擎1.5

创建Assets/Plugins/OpenHarmony/Bridge.etslib,内容如下

import { POST_MESSAGE_TO_HOST } from './workers/HostProxy';
import { MSG_RECEIVER, REGISTER_BUILTIN_MODULE } from './workers/MessageProcessor';
import tuanjie from 'libtuanjie.so'

export function RegisterBridge() {
  let register : Record<string, object> = {};
  register["Bridge"] = Bridge;
  return register;
}

// 导出给C#调用
export class Bridge {
  // 进行异步调用
  private static Call(funcName: string, param1: string) : void {
    console.log(`[SDK]CALL-${funcName}, param=${param1}`);
    let msg : ESObject = {}
    msg.funcName = funcName;
    msg.args = [ param1 ];
    msg.type = "RUN_ON_UI_THREAD_JS";
    POST_MESSAGE_TO_HOST(msg); // 团结引擎1.5的函数,让他在主线程中调用:模块名.函数名
  }
  public static Init(param: string): void {
    Bridge.Call("BridgeUI.SdkInit", param);
  }
  public static Login(param: string): void {
    Bridge.Call("BridgeUI.SdkLogin", param);
  }
}

// 异步调用的类
export class BridgeUI
{
  public static SendCSharp(funcName: string, result: string) : void {
    tuanjie.TuanjieSendMessage("MainCamera", funcName, result);
  }
  
  public SdkLogin(args: string) {
    console.log(`[SDK]ETS-Login=${args}`);
	SendCSharp("OnSdkLogin", "");
  }

  public SdkInit(args : string) {
    console.log(`[SDK]ETS-init=${args}`);
	SendCSharp("OnSdkInit", "");
  }
}

// 注册异常调用类
REGISTER_BUILTIN_MODULE(MSG_RECEIVER.HOST_UI,new BridgeUI())

在C#中建立HarmonyBridge.cs,代码如下,挂载到MainCamera节点上

using UnityEngine;
public class HarmonyBridge : MonoBehaviour
{
    private OpenHarmonyJSClass mOpenHarmonyJsClass;
    
    void Start()
    {
        mOpenHarmonyJsClass = new OpenHarmonyJSClass("Bridge");
    }


    public void OnInit(string result)
    {
    }

    public void OnLogin(string result)
    {
    }
	
    public void Init()
    {
        mOpenHarmonyJsClass.CallStatic("Init", "");
    }
	
    public void Login()
    {
        mOpenHarmonyJsClass.CallStatic("Login", "");
    }
}

团结引擎1.4

团结引擎1.4与1.5主线程调用有一定的区别

import tuanjie from 'libtuanjie.so'
import { CallOnUIThread } from './workers/TuanjieMainWorker';

export function RegisterBridge() {
 let register : Record<string, object> = {};
 register["Bridge"] = Bridge;
 return register;
}

// 导出给C#调用
export class Bridge {
  private static Call(funcName: string, param1: string) : void {
    // 在主线程中调用 BridgeUI.funcName 方法
    CallOnUIThread("../Bridge", "BridgeUI", funcName, [param1], null);
  }
  // C#脚本直接调用
  public static Init(param: string): void {
    Bridge.Call("SdkInit", param, ""); // 主线程调用BridgeUI.SdkInit
  }
  // C#脚本直接调用
  public static Login(param: string): void {
    Bridge.Call("SdkLogin", param, ""); // 主线程调用BridgeUI.SdkLogin
  }
}

export class BridgeUI
{
  public static SdkInit(args: string) : void {
	SendCSharp("OnInit", "arg1");
  }

  public static SdkLogin(args: string) {
    SendCSharp("OnLogin", "arg2");
  }
  // 调用C#MainCamera节点上面含有函数名为funcName的函数
  public static SendCSharp(funcName: string, result: string) : void {
    tuanjie.TuanjieSendMessage("MainCamera", funcName, result);
  }
}

注意,CallOnUIThread这个函数,在官方手册中一带而过

https://docs.unity.cn/cn/tuanjiemanual/1.4/Manual/openharmony-plugins-typescript-call-ui-thread-worker.html

因为CallOnUIThread这个函数位于entry/src/main/ets/workers/TuanjieMainWorker.ets文件中,所以

如果写moduleName时,需要以entry/src/main/ets/workers/作为起始目录进行查找

如果Bridge文件位于 entry/src/main/ets/ 目录中,则moduleName需要写成 “../Bridge”