UnityAndroid(2) Android加载Unity

目录

一、Android加载Unity

1.1 Unity打包Android项目

1.2 Android加载Unity生成项目

1.3 加载Unity内容

二、Unity和Android交互

2.1 Unity发消息给Java

2.2 Android发消息给Unity


开发环境:Unity2019.2.17f,AndroidStudio3.5.3,VS2019。

我要达到的功能是

1.在unity里面点击一个按钮,在Unity三维内容前面弹出一个窗口,显示Android内容。

2.在Android界面的一部分显示Unity的三维内容。

一、Android加载Unity

1.1 Unity打包Android项目

参考:Unity 工程 融合 AndroidStudio工程

Unity导出Android项目,AndroidStudio导入过程中提示了几个窗口

总之继续下去,打开项目。

下载SDK,能够正常导入了。

加入现在打包运行的话,看到的就是Unity程序了。

--------------------------------------------------------------------------

1.2 Android加载Unity生成项目

将刚刚导出的项目从application改成library,修改成类库。

根据错误提示把下面的bundle和applicationId注释掉

可以打包成aar文件了。

放入Android项目中的libs文件夹中

加入到项目中

Build后出现错误:Manifest merger failed with multiple errors, see logs

参考:https://blog.csdn.net/dengweijunkedafu/article/details/80541104

输入gradlew processDebugManifest --stacktrace,结果

总之把Unity导出项目里面的AndroidManifest.xml的<Application ...>里面的冲突的都删除了。

也就是前面教程中的

就像这样

可以Build了。

---------------------------------------------------------

1.3 加载Unity内容

接下来在Android界面中加载Unity的内容

private UnityPlayer mUnityPlayer;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.i("MainActivity","onCreate");
        //initUnityPlayer();
        Button btnInit=findViewById(R.id.btnInitUnity);
        btnInit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.i("MainActivity","btnInit onClick");
                initUnityPlayer();
            }
        });
    }
    private void initUnityPlayer() {
        try {
            Log.i("MainActivity","initUnityPlayer");
            LinearLayout layout = findViewById(R.id.unityview);
            mUnityPlayer = new UnityPlayer(this);
            layout.addView(mUnityPlayer.getView());
            mUnityPlayer.requestFocus();
        }catch (Exception ex){
            Log.e("MainActivity","Exception:"+ex);
        }
    }

运行测试的结果,initUnityPlayer放到onCreate或者onStart里面会闪退,而且没有提示。

加工按钮后,提示E/Unity: Failed to load 'libmain.so'

搜索E/Unity: Failed to load 'libmain.so',在百度上找不到相关资料,感觉它对于纯英文的比较无力....

libmain.so是Unity生成项目里面的

google到 https://forum.unity.com/threads/integration-unity-as-a-library-in-native-android-app.685240/

这个好像是Version1,还有个Version2

相关的还有:https://forum.unity.com/threads/using-unity-as-a-library-in-native-ios-android-apps.685195/

https://forum.unity.com/threads/integration-unity-as-a-library-in-native-android-app-version-2.751712/

感觉官方的教程不是aar加载而是作为一个Model加载进来的。

另外,有个官方Demo:https://github.com/Unity-Technologies/uaal-example

按照这个

把Unity生成项目的ndk拷贝过来

        ndk {
            abiFilters 'armeabi-v7a'
        }

结果,不崩溃了,但是还是出不来,那个要显示Unity的区域变成黑色了。

------------------------------------------------------------------------------------

经过研究、思考,理解UnityPlayer是什么,观察Unity打包项目的UnityPlayerActivity后,算是弄出来了。

把前面的initUnityPlayer放到onCreate中,同时把UnityPlayerActivity里面的其他Override方法都拷贝过来。

public class MainActivity extends AppCompatActivity {

    private UnityPlayer mUnityPlayer;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.i("MainActivity","onCreate");
        initUnityPlayer();
    }
    private void initUnityPlayer() {
        try {
            Log.i("MainActivity","initUnityPlayer");
            LinearLayout layout = findViewById(R.id.unityview);
            mUnityPlayer = new UnityPlayer(this);
            layout.addView(mUnityPlayer.getView());
            mUnityPlayer.requestFocus();
        }catch (Exception ex){
            Log.e("MainActivity","Exception:"+ex);
        }
    }

    @Override protected void onNewIntent(Intent intent) {
        // To support deep linking, we need to make sure that the client can get access to
        // the last sent intent. The clients access this through a JNI api that allows them
        // to get the intent set on launch. To update that after launch we have to manually
        // replace the intent with the one caught here.
        super.onNewIntent(intent);
        setIntent(intent);
        mUnityPlayer.newIntent(intent);
    }

    // Quit Unity
    @Override protected void onDestroy ()
    {
        mUnityPlayer.destroy();
        super.onDestroy();
    }

    // Pause Unity
    @Override protected void onPause()
    {
        super.onPause();
        mUnityPlayer.pause();
    }

    // Resume Unity
    @Override protected void onResume()
    {
        super.onResume();
        mUnityPlayer.resume();
    }
。。。。。

拷贝过来后,onNewIntent会让你加个super.onNewIntent。

运行后,在预定的区域(一个LinearLayout里面)显示了Unity的内容了

测试发现显示Unity内容是用mUnityPlayer.resume();,在requestFocus,马上resume的话,三维能够出来。按钮点击触发resume的话也能出来。

----------------------

直接继承UnityPlayerActivity其实就可以了

public class MainActivity extends UnityPlayerActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initUnityPlayer();
    }
    private void initUnityPlayer() {
        try {
            Log.i("MainActivity","initUnityPlayer");
            LinearLayout layout = findViewById(R.id.unityview);
            //mUnityPlayer = new UnityPlayer(this);
            layout.addView(mUnityPlayer.getView());//UnityPlayerActivity里面已经new了
            //mUnityPlayer.requestFocus();
        }catch (Exception ex){
            Log.e("MainActivity","Exception:"+ex);
        }
    }
}

-------------------------------------------

不过有发现,1.默认的标题栏不见了; 2.手机旋转时会崩溃退出

第一个不是问题,第二个必须处理。

直接横屏再打开是可以的。

Unity导出项目,生成运行测试,旋转不会崩溃。

。。。。。

===============================================================

二、Unity和Android交互

参考:Unity与Android Studio交互Unity 与 Android 互调用

2.1 Unity发消息给Java

    public void ClickF()
    {
        Debug.Log("ClickF");
        Count++;
        Result.text = Count + "";

        AndroidJavaClass jc = new AndroidJavaClass("com.example.myapplication.MainActivity");
        AndroidJavaObject overrideActivity = jc.GetStatic<AndroidJavaObject>("instance");
        int r=overrideActivity.Call<int>("UnityClick", Count);
        Result.text += "|" + r;
    }

Java中有相应的类->对象->方法,com.example.myapplication.MainActivity->instance->UnityClick。

public class MainActivity extends UnityPlayerActivity {
    public static MainActivity instance;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        instance = this;
        //...
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        instance = null;
    }
    public int UnityClick(int c){
        return c+1;
    }
}

2.2 Android发消息给Unity

// objectName: Unity 对象的名称
// methodName: Unity 对象绑定的脚本方法名
// message: 自定义消息
UnityPlayer.UnitySendMessage(String objectName, String methodName, String message);
        Button btn=findViewById(R.id.btnInitUnity);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                UnityPlayer.UnitySendMessage("JavaInterface","ReceiveFromAndroid","abc");
            }
        });

同样的Unity中必须有相应的GameObject->Function

public class JavaInterfaceABC : MonoBehaviour
{
    public void ReceiveFromAndroid(string a)
    {
        Debug.Log("ReceiveFromAndroid:" + a);
    }
}

类名不重要,重要的GameObject的名称。

另外假如JavaInterface对象上有多个脚本有ReceiveFromAndroid方法,都会被调用一次的。

-----------

总的来说,和Unity(Webgl)与Html交互很像。

因此实际功能开发时打算也是做成单一入口,所有的交互都从一个接口进入、一个接口出去,用json字符串的方式传递对象数据。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值