http://www.manew.com/thread-103445-1-1.html
Unity调用
接口
实践与总结(包含
Eclipse
和
AndroidStudio
)
根据前人及大神的教程,这次博客分享下本人对Unity和Android交互的实践与总结,分享下亲身踩坑的经历。
首先,介绍下工具和环境
System
|
Windows 8.1 Pro(64bit)
|
Unity Version
|
Unity 5.6.0f3(64bit)
|
IDE
|
①Visual Studio Ultimate 2013
②Eclipse Mars.2 Release (4.5.2)
③Android Studio 2.3.1
|
JDK Version
|
1.8.0_121
|
SDK Version
|
25.2.3
|
测试机Android
版本
|
4.4.2
|
目录:
一、AndroidStudio和Unity交互(导出ARR包)
二、Eclipse和Unity交互(导出JAR包)
三、AndroidStudio遇到的坑(错误解决方案)
四、Unity遇到的坑(错误解决方案)
一、先来聊聊AndroidStudio和Unity交互
1. 创建你的Unity 项目并设置player settings → settings for Android → Identification → PackageName(包名)和 Minimum API Level(最低支持的Android API版本)
<ignore_js_op>
2. 创建AndroidStudio Project
<ignore_js_op>
<ignore_js_op>
<ignore_js_op>
<ignore_js_op>
3. 添加依赖库并设置依赖关系
(1) 依赖库位置:
…\Unity 5.6.0f3\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes
<ignore_js_op>
(2) 将Classer.jar Cope到 libs 目录下。(本身是空的文件夹)
<ignore_js_op>
(3) 右键项目选择 Open Module Settings 或者直接按F4 打开 Project Structure窗口,并设置 Dependencies(依赖关系)。
<ignore_js_op> <ignore_js_op>
<ignore_js_op>
4. 编辑MainActivity.java
修改 MainActicity extends
(继承)UnityPlayerActivity
,然后编写功能
注释 setContentView(R.layout.activity_main);
[Java]
纯文本查看 复制代码
package
com.nick.unitytest;
import
android.app.AlertDialog;
import
android.os.Bundle;
import
android.os.Vibrator;
import
android.widget.Toast;
import
com.unity3d.player.*;
public
class
MainActivity
extends
UnityPlayerActivity {
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
}
// 定义一个显示Dialog的方法,在Unity中调用此方法
public
String ShowDialog(
final
String _title,
final
String _content){
runOnUiThread(
new
Runnable() {
@Override
public
void
run() {
AlertDialog.Builder builder =
new
AlertDialog.Builder(MainActivity.
this
);
builder.setTitle(_title).setMessage(_content).setPositiveButton(
"Down"
,
null
);
builder.show();
}
});
return
"Java return"
;
}
// 定义一个显示Toast的方法,在Unity中调用此方法
public
void
ShowToast(
final
String mStr2Show){
// 同样需要在UI线程下执行
runOnUiThread(
new
Runnable() {
@Override
public
void
run() {
Toast.makeText(getApplicationContext(),mStr2Show, Toast.LENGTH_LONG).show();
}
});
}
// 定义一个手机振动的方法,在Unity中调用此方法
public
void
SetVibrator(){
Vibrator mVibrator=(Vibrator)getSystemService(VIBRATOR_SERVICE);
mVibrator.vibrate(
new
long
[]{
200
,
2000
,
2000
,
200
,
200
,
200
}, -
1
);
//-1:表示不重复 0:循环的震动
}
// 第一个参数是unity中的对象名
// 第二个参数是函数名
// 第三个参数是传给函数的参数,目前只看到一个参数,并且是string
public
void
callUnityFunc(String _objName , String _funcStr, String _content)
{
UnityPlayer.UnitySendMessage(_objName, _funcStr,
"Come from:"
+ _content);
}
}
|
5. 编辑AndroidManifest.xml
添加元数据 <meta-dataandroid:name="unityplayer.UnityActivity"android:value="true" />
添加用户权限<uses-permissionandroid:name="android.permission.VIBRATE" />
[XML]
纯文本查看 复制代码
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
manifest
xmlns:android
=
"http://schemas.android.com/apk/res/android"
package
=
"com.nick.unitytest"
>
<
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"
>
<
activity
android:name
=
".MainActivity"
>
<
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"
/>
</
activity
>
</
application
>
<
uses-permission
android:name
=
"android.permission.VIBRATE"
/>
</
manifest
>
|
6. 编辑activity_main.xml
删除xmlns:app=http://schemas.android.com/apk/res-auto
删除app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
[XML]
纯文本查看 复制代码
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
android.support.constraint.ConstraintLayout
xmlns:android
=
"http://schemas.android.com/apk/res/android"
xmlns:tools
=
"http://schemas.android.com/tools"
android:layout_width
=
"match_parent"
android:layout_height
=
"match_parent"
tools:context
=
"com.nick.unitytest.MainActivity"
>
<
TextView
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:text
=
"Hello World!"
/>
</
android.support.constraint.ConstraintLayout
>
|
7. 编辑build.gradle
修改apply plugin: 'com.android.application'
为 applyplugin: 'com.android.library'
删除applicationId "com.nick.unitytest"
[Groovy]
纯文本查看 复制代码
apply plugin:
'com.android.library'
[/align][align=left]
android {
compileSdkVersion
25
buildToolsVersion
"25.0.3"
defaultConfig {
minSdkVersion
16
targetSdkVersion
25
versionCode
1
versionName
"1.0"
testInstrumentationRunner
"android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile(
'proguard-android.txt'
),
'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(include: [
'*.jar'
], dir:
'libs'
)
androidTestCompile(
'com.android.support.test.espresso:espresso-core:2.2.2'
, {
exclude group:
'com.android.support'
, module:
'support-annotations'
})
compile
'com.android.support.constraint:constraint-layout:1.0.0-alpha9'
testCompile
'junit:junit:4.12'
compile files(
'libs/classes.jar'
)
}
|
8. 导出并处理ARR
<ignore_js_op>
<ignore_js_op>
(1) Build 完之后 有个气泡弹出提醒,顺手点击Show in Explorer,错过了的话,可以在该工程的目录下找到
…\UnityTest\app\build\outputs\aar
<ignore_js_op>
(名字随意改啊)
(2) 打开ARR文件删除libs文件夹中的Classes.jar(这个是之前导入的依赖库,不删掉的话,在Unity项目中Build的时候会报“重复”的错)
<ignore_js_op> <ignore_js_op>
9. 导入Unity Project 中
(1) 在Assests 中新建Floder命名为“Plugins”,在“Plugins”文件夹中新建Floder命名为“Android”
<ignore_js_op>
(2) 将ARR文件放入“Android”文件夹中,并且从Android项目中复制一个AndroidManifest.xml一并放入文件夹中。
(3) 修改AndroidManifest.xml
这里一定要修改,不然Unity Build
的时候会报错,具体是报找不到资源的错
参照Unity
根目录下给出的AndroidManifest.xml
作修改依据
位置:…\Unity 5.6.0f3\Editor\Data\PlaybackEngines\AndroidPlayer\Apk
<ignore_js_op>
引用android:theme="@style/UnityThemeSelector"
android:icon="@drawable/app_icon"
android:label="@string/app_name"
android:debuggable="true"
作用:引用Unity
的图标主题及应用标题
[XML]
纯文本查看 复制代码
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
manifest
xmlns:android
=
"http://schemas.android.com/apk/res/android"
package
=
"com.nick.unitytest"
>
<
application
android:allowBackup
=
"true"
android:supportsRtl
=
"true"
android:theme
=
"@style/UnityThemeSelector"
android:icon
=
"@drawable/app_icon"
android:label
=
"@string/app_name"
android:debuggable
=
"true"
>
<
activity
android:name
=
".MainActivity"
>
<
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"
/>
</
activity
>
</
application
>
<
uses-permission
android:name
=
"android.permission.VIBRATE"
/>
</
manifest
>
|
10. 创建场景,添加脚本,Build APK
塞几个按钮大家都懂,不细说。脚本搞定,把方法挂上按钮就好了。
<ignore_js_op>
脚本如下:
[C#]
纯文本查看 复制代码
using
System.Collections;
using
System.Collections.Generic;
using
UnityEngine;
using
UnityEngine.UI;
public
class
UnityTest : MonoBehaviour
{
public
Text mText;
public
void
BeCallFunc(
string
_content)
{
setMsg(
ref
_content);
}
private
void
setMsg(
ref
string
_str)
{
mText.text = _str;
}
public
void
Btn_Dialog()
{
// Java Interface Of Android
AndroidJavaClass jc =
new
AndroidJavaClass(
"com.unity3d.player.UnityPlayer"
);
AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>(
"currentActivity"
);
// Parameters
string
[] mObject =
new
string
[2];
mObject[0] =
"Jar4Android"
;
mObject[1] =
"Wow,Amazing!It's worked!"
;
// Func
string
ret = jo.Call<
string
>(
"ShowDialog"
, mObject);
setMsg(
ref
ret);
}
public
void
Btn_Toast()
{
AndroidJavaClass jc =
new
AndroidJavaClass(
"com.unity3d.player.UnityPlayer"
);
AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>(
"currentActivity"
);
jo.Call(
"ShowToast"
,
"Showing on Toast"
);
}
public
void
Btn_Vibrate()
{
AndroidJavaClass jc =
new
AndroidJavaClass(
"com.unity3d.player.UnityPlayer"
);
AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>(
"currentActivity"
);
jo.Call(
"SetVibrator"
);
}
public
void
Btn_CallBack()
{
AndroidJavaClass jc =
new
AndroidJavaClass(
"com.unity3d.player.UnityPlayer"
);
AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>(
"currentActivity"
);
jo.Call(
"callUnityFunc"
,
"Canvas"
,
"BeCallFunc"
,
"Nick LAM"
);
}
}
|
11. 要点总结
①
添加元数据添加用户权限
②
修改gradle
脚本使导出的为library
③
修改layout
布局文件
④
删除ARR
包中libs
的Classes.jar
⑤
导入Unity
时修改AndroidManifest
的资源引用
二、聊聊Eclipse和Unity交互
1. 创建你的Unity Project 同上,注意Package Name 同 Minimum API Level
2. 創建Eclipse Android Project
<ignore_js_op>
<ignore_js_op>
<ignore_js_op>
<ignore_js_op>
3. 添加依赖库
两种方法:
(1) Add External JARs(添加外部JAR包)
<ignore_js_op>
(2) 创建“libs” 文件夹,并将依赖库cope文件夹下
<ignore_js_op>
4. 编辑MainActivity.java
同上啦!就不累赘
5. 编辑AndroidManifest.xml
添加元数据 <meta-dataandroid:name="unityplayer.UnityActivity"android:value="true" />
添加用户权限<uses-permissionandroid:name="android.permission.VIBRATE" />
[XML]
纯文本查看 复制代码
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
manifest
xmlns:android
=
"http://schemas.android.com/apk/res/android"
package
=
"com.nick.unitytest"
android:versionCode
=
"1"
android:versionName
=
"1.0"
>
<
uses-sdk
android:minSdkVersion
=
"16"
android:targetSdkVersion
=
"18"
/>
<
application
android:allowBackup
=
"true"
android:icon
=
"@drawable/ic_launcher"
android:label
=
"@string/app_name"
android:theme
=
"@style/AppTheme"
>
<
activity
android:name
=
".MainActivity"
android:label
=
"@string/app_name"
>
<
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"
/>
</
activity
>
</
application
>
</
manifest
>
|
6. 导出并处理JAR
(1
)导出操作:右键Project → Export → Java → JAR file
<ignore_js_op> <ignore_js_op>
(2
)打开JAR
文件删除libs
文件夹中的Classes.jar
(这个是之前导入的依赖库,不删掉的话,在Unity
项目中Build
的时候会报“
重复”
的错)
<ignore_js_op> <ignore_js_op>
7. 导入UnityProject
(1) 在Assests 中新建Floder命名为“Plugins”,在“Plugins”文件夹中新建Floder命名为“Android”
<ignore_js_op>
(2) 将ARR文件放入“Android”文件夹中,并且从Eclipse 的Android项目中复制一个AndroidManifest.xml一并放入文件夹中。
(3) 修改AndroidManifest.xml
这里一定要修改,不然Unity Build
的时候会报错,具体是报找不到资源的错
参照Unity
根目录下给出的AndroidManifest.xml
作修改依据
位置:…\Unity 5.6.0f3\Editor\Data\PlaybackEngines\AndroidPlayer\Apk
引用android:theme="@style/UnityThemeSelector"
android:icon="@drawable/app_icon"
android:label="@string/app_name"
android:debuggable="true"
作用:引用Unity
的图标主题及应用标题
[XML]
纯文本查看 复制代码
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
manifest
xmlns:android
=
"http://schemas.android.com/apk/res/android"
package
=
"com.nick.unitytest"
android:versionCode
=
"1"
android:versionName
=
"1.0"
>
<
uses-sdk
android:minSdkVersion
=
"16"
android:targetSdkVersion
=
"18"
/>
<
application
android:allowBackup
=
"true"
android:theme
=
"@style/UnityThemeSelector"
android:icon
=
"@drawable/app_icon"
android:label
=
"@string/app_name"
android:debuggable
=
"true"
>
<
activity
android:name
=
".MainActivity"
android:label
=
"@string/app_name"
>
<
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"
/>
</
activity
>
</
application
>
<
uses-permission
android:name
=
"android.permission.VIBRATE"
/>
</
manifest
>
|
8. 创建场景,添加脚本,Build APK
同上啦!就不累赘了。
9. 要点总结
①
添加元数据添加用户权限
②
删除JAR
包中libs
的Classes.jar
③
导入Unity
时修改AndroidManifest
的资源引用
三、AndroidStudio遇到的坑:
①
问题:
,升级完成后新建项目的时候遇无限Building“project name”gradle project info
原因:AS
的每个版本会有对应的Gradle
标配版本,所以它得把Gradle
升级到标配版本
解决方法:
下载Gradle
离线包去手动更新(幸运的是,我正打算去下载离线包,它居然在祖国伟大的防火墙里经历了半个小时候后,顽强的帮我更新成功了)
②
问题:SDKTools
更新到最新的版本26.0.1
,会报错
<ignore_js_op>
<ignore_js_op> (错误:无效的命令 android)
(另外还有个问题就是更新到最新的版本
26.0.1
,内置的
SDK Manager.exe
就无法使用了)
原因:
因为最新的SDK Tools
版本是不带命令行工具的,而Unity Build
安卓App
要用到命令行工具
解决方案:1.
如果你不慎更新了最新的版本,你可以到SDK
官网单独下载带命令行的SDKTools
(他给出带命令行工具的版本是25.2.3
,内置SDK Manager
给出的更新提示可以升级到25.2.5
,我没有去尝试,也不知道这个版本有没有带命令行工具,欢迎大家尝试后留言告诉我);2.
如果你没有更新到最新的版本,请注意在打开Android Studio
的SDK Manager
缺选SDK Tools
四、Unity 遇到的坑:
①
问题:.2.2
的版本当SDK Build-Tools
≥24.x.x
的时候会报错
原因:
不支持呗
解决方案:
把高版本的Hide
起来,just like me
<ignore_js_op>