Android Studio工程与Unity工程的交互与进一步封装

在unity中的回调事件如果需要暴露给AS工程监听的话,可以在自己的工程下创建一个Plugins文件夹,在子文件夹下再添加Android文件夹,这个Android文件夹下创建的java类或者jar、aar包在unity工程输出AS包的时候会一同打包出去。

举个例子,当unity工程中有个加载场景的方法,在加载时会不断返回加载的进度,在加载完成后回调加载完成事件。如果要把这个加载场景的方法暴露给AS工程进行调用,AS工程是不能直接在一个方法里把加载中、加载完成的监听放进加载方法中的。

因为AS调用Unity的方法,只能通过以下方式进行调用

/*
gameObj----unity挂载调用类的gameobject物体的name
function----unity中触发的类
param----unity中触发的类的参数
*/
UnityPlayer.UnitySendMessage("gameObj","function","param")

这种机制的话,如果方法中需要把监听事件传进去让回调监听是无法直接实现的,不过如果懂一点AS基础的话,就可以在AS工程中把对应的监听事件进一步封装,整合成一个方法的形式,下面说下具体的做法。

首先是在unity工程中,在Plugins/Android下创建的java类用于标记需要监听的回调方法。按照上面的例子,加载场景的话需要监听加载进度与加载完成事件。那么可以创建一个CallbackActivity.java,里面的代码如下所示:

package com.XXX.XXXX;
import android.os.Bundle;
import android.widget.FrameLayout;

import com.unity3d.player.UnityPlayerActivity;

public abstract class CallbackActivity extends UnityPlayerActivity
{
    public static CallbackActivity instance = null;

    abstract protected void loadSceneComplete();//加载完成的监听事件
    abstract protected void loadSceneProcess(String percent);//加载中的监听事件


    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        instance = this;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        instance = null;
    }
}

这两个监听的回调在Unity触发加载场景的方法时不断触发。下面是unity的代码

    /// <summary>
    /// 加载场景
    /// </summary>
    /// <param name="content"></param>
    public void LoadScene(string content)
    {
        #if UNITY_ANDROID
        AndroidJavaClass jc = new AndroidJavaClass("com.XXX.XX.CallbackActivity");
        AndroidJavaObject activity = jc.GetStatic<AndroidJavaObject>("instance");
        #endif
        rbxManager.LoadScene(sceneID,Progress.Create<float>(percent =>
        {
        #if UNITY_ANDROID
            activity.Call("loadSceneProcess", precent.ToString());
        #endif
        }), ()=> {
        #if UNITY_ANDROID
            activity.Call("loadSceneComplete","");
        #endif

        });

    }

正常的逻辑是当AS工程中调用了UnityPlayer.UnitySendMessage("gameObj","LoadScene","content")方法来 加载场景时,需要在继承上面的CallbackActivity类中override掉loadSceneComplete和loadSceneProcess这两个方法才能监听。代码如下所示:

public class UnityCallbackActivity extends CallbackActivity {    
@Override
    protected void loadSceneComplete() {
        //监听
    }
@Override
    protected void loadSceneProcess(String percent) {
        //监听
    }
}

到这一步为止就是默认的做法,通过UnityPlayer.UnitySendMessage来触发加载,然后在复写的方法里面监听事件。

如果导出的Unity工程是自己使用当然没问题,但如果把工程提供给不懂3D开发的AS开发工程师的话,理解起来就有点绕,个人认为需要上方法上进一步封装,把方法的调用与监听都放在同一个函数里面。

首先是委托的重写。java跟C#不太一样,没有Action这个种系统内置的委托类型,而是通过接口的方式来实现委托的。

拿上面加载场景的例子来说。对应loadSceneComplete与loadSceneProcess这两个回调的方法,需要重新定义两个对应接口的java类

package com.realibox.ar.callback;

public interface LoadSceneCallback{
    public void loadSceneAction(float percent);
}
package com.xxx.xxxx.callback;

public interface LoadSceneComleteCallback{
    public  void loadSceneCompleteAction();
}

然后在上面的UnityCallbackActivity.java进一步修改,代码如下

public class UnityCallbackActivity extends CallbackActivity {    
    /*
    *when scene loading complete, this function will callback
     */
    private LoadSceneComleteCallback loadSceneComleteCallback;
    @Override
    protected void loadSceneComplete() {
        if (loadSceneComleteCallback!=null)
        loadSceneComleteCallback.loadSceneCompleteAction();
    }

    /*
    * when scene is loading, this function will stay callback
     */
    private LoadSceneCallback loadSceneCallback;
    @Override
    protected void loadSceneProcess(String percent) {
        if (loadSceneCallback!=null) {
                loadSceneCallback.loadSceneAction(p);
        }
    }
}

上面实现的逻辑就是当Unity回调这两个事件时,继承这两个接口的类的方法也会触发。

这样的话,在AS工程中,调用场景的方法就可以进一步封装,代码如下:

    void Init(){
                LoadProject(sceneId, 
                    percent -> {
                        Log.e(TAG, "percent-"+percent);
                    }, 
                    () -> {
                        Log.e(TAG, "loadsenecomplete");
                    });
    }

    /*
     *
     * scene_id
     * LoadSceneCallback:return percent of load scene
     * LoadComleteCallback:callback when finish load scene
     */
    protected void LoadProject(String sceneid, String doMain,LoadSceneCallback loadSceneCallback,LoadSceneComleteCallback loadSceneComleteCallback) {
        UnityPlayer.UnitySendMessage("gameobj", "LoadScene", sceneid);
        this.loadSceneCallback = loadSceneCallback;
        this.loadSceneComleteCallback = loadSceneComleteCallback;

    }   

这样的话当调用加载场景的方法时,可以把加载中与加载完成的回调都当成参数传进方法里面。

猜你喜欢

转载自blog.csdn.net/ssssssilver/article/details/108466721