【Unity3D学习记录#2】Android调用Unity界面 与 信息交互
Android 调用 Unity
之前一直在Unity平台上进行开发,被Unity的界面设计困扰,于是想将文字、图片的主要功能放到Android平台上,中间踩过很多的坑,现在将我的步骤总结,希望对后面进行类似工作的朋友有所帮助。本文仅进行最基本的功能测试,用例极为简单,如有其它功能需求,还请自行添加。因为没有经过系统Android学习,使用的术语不准确,如对理解产生障碍,还请见谅。
Unity项目构建
本文使用的Unity3D版本:2019.3.0f6
具体步骤:
1、构建新的3D项目
首先,项目发布平台选择Android,这一步的目的是为了对Game视图进行修改,方便界面的设计与实现(本文选择的视图选项为:1920 x 1080 Portrait(1080 x 1920))。这一步的前提是你已经配置好JDK、SDK的配置,配置的过程在论坛中有很多教程,这里推荐直接使用Unity Hub对Unity3D配置、版本进行管理,能够大大降低出错的可能性。(Unity与Android尽量使用同样的JDK和SDK,否则容易出错)
在场景中建立如下物体:
(1)Text:用来显示接收到的信息
建立Text后会自动建立一个Canvas,需要对其参数进行修改
(2)Button:触发测试代码
(3)Cube:早先留做测试,现已弃用,如不需要操作场景和脚本中可以忽略
建立好的界面大致如下图所示:
2、编写并挂载脚本 Test.cs
using UnityEngine;
using UnityEngine.UI;
public class Test : MonoBehaviour
{
public Text mtext;
//一个旋转物体(弃用)
public GameObject cube;
void Update()
{
if (Input.GetKeyDown(KeyCode.Escape) || Input.GetKeyDown(KeyCode.Home) )
{
Application.Quit();
}
}
public void OnClick()
{
print("OnClick执行");
/* com.njucm.unity2android : Android工程定义的包名
* UnityActivity :java方法(函数)所在的类 */
using (AndroidJavaClass jc = new AndroidJavaClass("com.njucm.android2unity.UnityActivity"))
{
print("Android包寻找成功");
//jc.CallStatic("sendmessage");
using (AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("m_instance"))
{
print("调用m_instance,尝试调用对象下的非静态函数");
if (jo != null)
{
jo.Call("sendmessage");
}
else
{
print("m_instance获取失败");
}
}
}
//m_instance : UnityPlayerActivity类中自己声明
}
public void settextView(string str)
{
print("收到了Android信息,str:" + str);
mtext.text = str;
}
}
这一部分代码的主要功能为:
①通过AndroidJavaClass,利用Android项目中的包名、类名,获取java中的类。
AndroidJavaClass jc = new AndroidJavaClass(“com.njucm.android2unity.UnityActivity”)
②通过AndroidJavaObject,获取类UnityActivity内的静态数据成员作为对象(Android正在运行的界面)
AndroidJavaObject jo = jc.GetStatic(“m_instance”)
③通过AndroidJavaObject.Call(“函数名”),调用java中的函数(可以加入参数值,但是本文的Android项目内方法没有设置参数,具体使用方法可以到论坛上搜索其他的文章)
jo.Call(“sendmessage”);
脚本需要挂载在Main Camera、Button上,请不要忘记将脚本中的参数实例化(绑定脚本后,拖动场景中的物体进行赋值)。
Button点击事件需要绑定OnClick()函数。
3、项目的导出
依次(->) 点击/执行操作
-> File
-> Build Settings
-> 在Scenes in Build中添加创建的场景
-> Player Settings
-> 修改Company Name、Product Name(本文中分别为njucm、android2unity)
-> Other Settings
-> Package Name,对照内容是否为“com.{Company Name}.{Product Name}”。({ }表示必填,[ ]表示选填)
-> 设置Minimun API Level (本文选择的版本为API Level 19)
-> Player Settings页面设置完毕,回到Build Settings
-> 勾选Export Project
-> 点击Export导出,记住放在哪里了,等等要用
Android项目构建
1、新建Android项目
(1)建立一个Empty Activity
(2)设置Android包名、MIni API Level(需与Unity设置一致)
2、引入之前建立好的Unity项目
依次(->) 点击/执行操作
-> File=>New => Import Module
-> 选择刚刚Unity导出的文件夹,保证launcher和unityLibrary选中,导入(图片是已经导入过了,正常情况不会报错)
-> File->Project Structure->Dependencies
-> 给uniyLIbrary加上unity-classes.jar文件依赖(否则会引起UnityPlayer无法使用)给app加上unityLibrary环境依赖,点击OK(新版本的Android Studio可以不修改复杂的代码就可以进行依赖的修改,但是细节处需要自己调整)
-> 修改依赖方式:
资源管理器 => Gradle Scripts => build.gradle(Module:untiyLibrary) => dependencies{} => 修改关于unity-classes.jar的引用语句:
implementation files(‘libs\unity-classes.jar’)
修改成:
api files(‘libs\unity-classes.jar’)
否则会引起UnityPlayer无法使用。
关于api和implementation两种依赖方式的不同还请到论坛查找,这里不做赘述。
->重新Biuld项目,如未报错则说明导入成功,且依赖修改成功
Android 与 Unity 的信息交互
承接上文
3、修改AndroidManifest.xml文件,要修改两个
(1)untiyLibrary=>manifests文件夹下的:注释掉< intent-filter>标签;
(2)app=>manifests文件夹下的:在之前的< activity></ activity>标签后添加Unity项目的activity(根据代码提示工具即可,现有结果为:
< activity android:name=“com.unity3d.player.UnityPlayerActivity”/>’)
另外,如果这个文件有大片的警示,如下图所示,请将光标放在警示的代码段上,按下alt+enter,根据提示修改错误(否则会页面闪退)
4、修改strings.xml文件。
-> 资源管理器(Android视图):app=>res=>values=>strings.xml
-> 在之前的标签下添加如下语句,否则会Unity页面闪退
< string name=“game_view_content_description”>Game view</ string>
5、编辑java文件。
app=>java=>{包名}文件夹下建立 UnityActivity.Java文件(原文件夹下有MainActivity文件,在这里先不做修改,后面会有其他的操作,总之,后面不会使用这个文件,主要原因是Unity的代码已经写好了,懒得再弄一遍了,嘻嘻,后面你可以自己修改),编写代码:
package com.njucm.android2unity;
import android.app.Activity;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerActivity;
public class UnityActivity extends UnityPlayerActivity {
private Button loadBtn;
protected UnityPlayer mUnityPlayer;
public static UnityActivity m_instance=null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//
loadBtn = findViewById(R.id.loadBtn);
//
loadBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivity(new Intent(UnityActivity.this,UnityPlayerActivity.class));
}
});
m_instance = this;
}
public void sendmessage()
{
UnityPlayer.UnitySendMessage("Main Camera","settextView","this is the message from android");
}
}
这个时候R.id.loadBtn会报错,是因为还有文件没有编写完,不用担心。
在Android中我们使用
UnityPlayer.UnitySendMessage("{Object Name}",“Function Name”[,“parameter values”);
方法给Unity的脚本发送消息,实现信息的发送
6、编写app=>res=layout=>activity.xml文件
比较简单,不再多说,内容如下:
<?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=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/loadBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Open Unity"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.374"
tools:ignore="HardcodedText" />
</androidx.constraintlayout.widget.ConstraintLayout>
这个时候R.id.loadBtn报错会消失
7、修改app=>manifests文件夹下的AndroidManifest.xml文件
添加新的UnityActivity,并将其设为MainActivity(首先打开的),修改前内容如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.njucm.android2unity">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.unity3d.player.UnityPlayerActivity"/>
</application>
</manifest>
修改后内容如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.njucm.android2unity">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">
<activity android:name=".MainActivity">
</activity>
<activity android:name="com.unity3d.player.UnityPlayerActivity"/>
<activity android:name=".UnityActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
8、重新Build项目,运行一下试试吧
可以看到,我们成功打开了Unity的界面,并且在Unity的界面调用了android方法,给Unity发送了消息,修改了Unity的场景物体属性值,实现了极为简单的交互。
结语
本文旨在明确 android调用Unity界面并进行信息交互 实现过程中的问题和步骤,更加复杂的内容还是请各位实现,希望这篇文章能给同行者一些帮助。
至此,完本文毕。
参考文献
1、https://blog.csdn.net/m0_38096376/article/details/69567409
2、https://www.jianshu.com/p/b5e3cfcdf081
3、https://www.jianshu.com/p/b4d5a9afcc99
4、https://blog.csdn.net/qq_39091751/article/details/84023996?ops_request_misc=&request_id=&biz_id=102&utm_term=android%20unity%20%E4%BA%A4%E4%BA%92&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-9-84023996.pc_search_result_no_baidu_js