ARFoundation入门教程4-android接入AR unity工程

源代码GitHub - sueleeyu/arunitylib: 导出lib的unity工程

一、unity 导出lib工程

1.unity编写脚本AndroidHandler.cs,挂载到AR Camera上,(AR Camera的name为MainCamera,对应MainActivity中CallUnityFun的receiveObj

2. AndroidHandler.cs增加调用unit调用android的代码:

public void OnClickToJavaFunSum()

        {

            AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.MainActivity");

            AndroidJavaObject jo = jc.CallStatic<AndroidJavaObject>("GetInstance");

            messageText.text = jo.Call<int>("Sum", 5, 3).ToString();

        }

3. AndroidHandler.cs增加android to unity的回调:

public void Receive(string str)

扫描二维码关注公众号,回复: 14625182 查看本文章

        {

            receiveMessageText.text = str;

        }

4.AndroidHandler.cs:

using UnityEngine;

using UnityEngine.UI;

namespace UnityEngine.XR.ARFoundation.Samples

{

    public class AndroidHandler : MonoBehaviour

    {      

        private AndroidJavaObject javaObject;//MainActivity对象

        [SerializeField]

        private Text messageText;//unity场景显示Text

        [SerializeField]

        private Text receiveMessageText;//unity场景显示Text

        // Start is called before the first frame update

        void Start()

        {

            //第二种

            AndroidJavaClass android = new AndroidJavaClass("com.unity3d.player.UnityPlayer");

            javaObject = android.GetStatic<AndroidJavaObject>("currentActivity");

        }

        public void OnClickToJavaFunSum()

        {

            AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.MainActivity");

            AndroidJavaObject jo = jc.CallStatic<AndroidJavaObject>("GetInstance");

            messageText.text = jo.Call<int>("Sum", 5, 3).ToString();

        }

        public void OnClickToJavaFunSum2()

        {           

            messageText.text = javaObject.Call<int>("Sum", 5, 3).ToString();

        }      

        public void OnClickCall1()//android调用unity的启动示例,unity调用android的CallUnityFun方法,通过UnityPlayer.UnitySendMessage向unity发送消息

        {

            AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.MainActivity");//MainActivity继承UnityPlayerActivity

            AndroidJavaObject jo = jc.CallStatic<AndroidJavaObject>("GetInstance");//GetInstance方法获取的当前对象

            jo.Call("CallUnityFun", "Test2");//调用android端方法CallUnityFun

        }

        public void OnClickCall2()

        {

            javaObject.Call("CallUnityFun", "Test1");//调用android端方法CallUnityFun

        }

        //接收来自android的参数

        public void Receive(string str)

        {

            receiveMessageText.text = str;

        }

    }

}

5. unity增加调用android按钮事件:

Unity场景新建Button,新增挂载OnClick方法,选择AndroidHander-OnClickToJavaFunSum

6. unity中增加android调用unity按钮事件:

Unity场景新建Button,新增挂载OnClick方法,选择AndroidHander- OnClickCall1

7.unity中增加2个调用展示Text:

u call a,a call u

8.File-build setting player setting修改导出设置:

9.File-build settings-Android,导出为android工程。

    

二、android studio中导入

1.新建或打开android工程,包名:com.xxx.xxxxx同unity一样

 (包名可以不同)

2.拷贝导出的Unity下的 unityLibrary 到 安卓工程根目录

3.打开setting.gradle,增加:

include ':unityLibrary'

4.打开gradle.properties,增加:

unityStreamingAssets=.unity3d

5.打开local.properties,增加你的NDK路径:

6.Projectbuild.gradlerepositories增加:

flatDir {
      
      

dirs "${
      
      project(':unityLibrary').projectDir}/libs"

}

7.appbuild.gradle增加ndk
ndk {

    abiFilters 'armeabi-v7a'

}
 
 

8.appbuild.gradle增加dependencies
implementation project(':unityLibrary')
 
 

 
 

 
 
9.appandroidmanifest.xmlapplication增加:

<application
   
android:extractNativeLibs="true"

 
 
10.运行:
 
 

三、配置修改导入后的unity库

1.unityLibrary增加MainActvity,继承UnityPlayerActivity,代码都在MainActivity中编写:

package com.unity3d.player;

import android.os.Bundle;

import android.view.KeyEvent;



public class MainActivity extends UnityPlayerActivity{



    private static MainActivity instance;



    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        instance = this;

    }



    public static MainActivity GetInstance()

    {

        return instance;

    }



    @Override public boolean dispatchKeyEvent(KeyEvent event)

    {

        if(event.getKeyCode() == KeyEvent.KEYCODE_BACK){

            onBackPressed();

            return true;

        }



        if (event.getAction() == KeyEvent.ACTION_MULTIPLE)

            return mUnityPlayer.injectEvent(event);

        return super.dispatchKeyEvent(event);

    }



    //------

    @Override

    public void onBackPressed() {

        runOnUiThread(new Runnable() {

            @Override

            public void run() {

                mUnityPlayer.quit();

            }

        });

        super.onBackPressed();

    }



    //unity调用android的方法

    public int Sum(int x, int y)

    {

        return x + y;

    }

    public void CallUnityFun(String str)

    {

        String receiveObj = "MainCamera";//unity中脚本挂载的Objectname

        String receiveMethod = "Receive";//unityObject挂载脚本的方法名

        String params = str + " Android Call Unity.";//方法要穿的参数

        //android调用unity,

        UnityPlayer.UnitySendMessage(receiveObj, receiveMethod, params);

    }

}
 
 
2.修改unityLibrary的manifest文件,UnityPlayerActivity改为MainActivity:

android:name="com.unity3d.player.MainActivity"

四、android和unity的相互调用

UnitySendMessage方法的使用:

UnitySendMessage在android端调用,在回调方法被触发时,通过UnitySendMessage方法把结果发给unity,让unity这边处理。UnitySendMessage(“string”,“string”, ***),这是方法,我们至少需要传入两个参数,第一个参数为unity中的cs代码挂载的gameobject名称(本例AR Camera的name为MainCamera,对应MainActivity中CallUnityFun的UnitySendMessagereceiveObj=” MainCamer

,第二个参数为这个gameobject身上捆绑的脚本中的一个方法,而第三参数事实上是这个对应方法上的参数,有没有参数就看你了。
1.app的Strings.xml增加如下,否则会报错:

<string name="game_view_content_description">Game view</string>

2.android代码MainActivity增加调用代码,如下:

package com.suelee.libtest;



import androidx.appcompat.app.AppCompatActivity;



import android.content.Intent;

import android.os.Bundle;

import android.view.View;

import android.widget.TextView;

import android.widget.Toast;





public class MainActivity extends AppCompatActivity {

    public static final int REQUSET = 1;

    private TextView tv01;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        tv01 = (TextView) findViewById(R.id.tv01);

        findViewById(R.id.callJs).setOnClickListener(new View.OnClickListener() {

            @Override

            public void onClick(View v) {

                tv01.setText("调用");

                Intent intent = new Intent(MainActivity.this,

                        com.unity3d.player.MainActivity.class);

                //发送意图标示为REQUSET=1

                startActivityForResult(intent, REQUSET);

                //startActivity(new Intent(MainActivity.this, UnityPlayerActivity.class));

            }

        });

    }

    @Override

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    
    //请求参数、返回参数、返回的intent

        // TODO Auto-generated method stub

        super.onActivityResult(requestCode, resultCode, data);

        //requestCode标示请求的标示   resultCode表示有数据

        if (requestCode == MainActivity.REQUSET && resultCode == RESULT_OK) {



        }

        String str = "unity返回";

        runOnUiThread(new Runnable() {

            @Override

            public void run() {

                tv01.setText(str);

            }

        });



        Toast.makeText(

                this,

                "requestCode=" + requestCode + ":" + "resultCode=" + resultCode,

                Toast.LENGTH_LONG).show();

    }

}
3. activity_main
<?xml version="1.0" encoding="utf-8"?>

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:app="http://schemas.android.com/apk/res-auto"

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    tools:context="com.suelee.libtest.MainActivity">



    <TextView

        android:id="@+id/tv01"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:text="Android App页面"

        app:layout_constraintBottom_toBottomOf="parent"

        app:layout_constraintLeft_toLeftOf="parent"

        app:layout_constraintRight_toRightOf="parent"

        app:layout_constraintTop_toTopOf="parent" />

    <Button

        android:id="@+id/callJs"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:text="调用unity AR"

        android:textAllCaps="false"

        tools:ignore="MissingConstraints" />

</androidx.constraintlayout.widget.ConstraintLayout>
4.运行:
 
 

 
 

五、常见问题

1. NDK was located by using ndk.dir property. This method is deprecated and will be removed in a future release. Please use android.ndkVersion or android.ndkPath in build.gradle to specify the NDK to use. https://developer.android.com/r/studio-ui/ndk-dir

解决:在模块的 build.gradle 文件中使用 android.ndkVersion 属性指定相应的版本,如以下代码示例所示,android下加:

android {

    ndkVersion = "major.minor.build" // e.g.,  ndkVersion "21.3.6528147"

}

2. Caused by: java.lang.RuntimeException: Duplicate class androidx.annotation.AnimRes found in modules annotation-1.3.0 (androidx.annotation:annotation:1.3.0) and jetified-com.android.support.support-annotations-26.1.0 (com.android.support.support-annotations-26.1.0.jar)

解决:删掉unityLIbrary下lib下对应的jar文件

3.打包出现duplicate,删除unityLIbrary下libs下对应的jar文件和buil.gradle里的对应implementation
4.

解决:禁用intel显卡驱动

5.unity返回android的activity会退出:

Androidmenufest中增加android:process=":UnityActivity"android:launchMode="singleInstance"android:launchMode="standard"
 
 

<activity android:name="com.unity3d.player.MainActivity" android:process=":UnityActivity" android:theme="@style/UnityThemeSelector" android:screenOrientation="fullSensor" android:launchMode="singleInstance" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale|layoutDirection|density" android:hardwareAccelerated="false">
  <
intent-filter>
    <
action android:name="android.intent.action.MAIN" />
    <
category android:name="android.intent.category.LAUNCHER" />
  </
intent-filter>
  <
meta-data android:name="unityplayer.UnityActivity" android:value="true" />
  <
meta-data android:name="android.notch_support" android:value="true" />
  <
meta-data android:name="android.notch_support" android:value="true" />
</
activity>

六、参考和代码

1.Unity api:Unity - Manual: Unity User Manual 2021.3 (LTS)

2.ARFoundation示例:

GitHub - Unity-Technologies/arfoundation-samples: Example content for Unity projects based on AR Foundation

3.源代码GitHub - sueleeyu/arunitylib: 导出lib的unity工程

猜你喜欢

转载自blog.csdn.net/weixin_40239288/article/details/125598497
今日推荐