背景

Unity开发过程中,自身提供的API或方案无法满足需求时,就需要Android工程交互通信。网络上交互方案很多,通常为jar包和aar包,经过对比本人采用aar包来实现,过程相对简单。

Unity自带的手机震动API, Handheld.Vibrate(); 可见简单的实现手机震动,但是手机震动时长是固定的1次0.5秒。无法控制震动的时长和次数。

实现效果

本案例可实现文本通信交互,Unity到Android,Android到Unity都能实现,最主要的手机震动控制也可实现,无论是时长还是次数。

方案配置

AndroidStudio 3.0 (亲测通过)
Unity 2018.4 (亲测通过)

方案优势

方案流程简单,不必匹配Unity的项目名和包名
不需要引用unity下的class.jar
不用在Unity的/Plugins/Android下放置AndroidManifest.xml文件
发布简单,只需要导出arr并直接拷贝到/Plugins/Android目录下即可使用,不用对文件做任何修改

流程

Android部分

  • 创建AndroidStudio工程
    1.打开AndroidStudio
    2.点击Start a new Android Studio project
  • android 振动权限 安卓震动api_安卓与unity通信

  • 编写AndroidStudio工程信息
    1.application name 随意,后面也不会用这个工程
    2.存放在合适的位置,记下来之后要找到文件
    3.点击下一步Next
  • android 振动权限 安卓震动api_安卓与unity通信_02

  • AndroidStudio工程配置
    1.API的档位尽可能小,能用就行
    2.其它部分不用管
    3.点Next下一步
  • android 振动权限 安卓震动api_unity_03

  • 创建空的Activity
  • android 振动权限 安卓震动api_安卓与unity通信_04

  • 直接下一步
  • android 振动权限 安卓震动api_安卓与unity通信_05

  • 添加自己的模块

1.在右上角选择为Android

2.右键app选择New

3.点击Module模块

android 振动权限 安卓震动api_android_06

  • 设置自己的模块

1.选择Android Library

2.点击Next下一步

3.填写Library的名称,这个名称很重要

4.点击Finish完成

android 振动权限 安卓震动api_unity_07

android 振动权限 安卓震动api_unity_08

  • 设置自己的模块添加Java脚本
    1.在自己的模块下 a2ulibrary/java/com.carol.a2ulibrary,这个目录下右键
    2.New 一个,JavaClass
    3.给JavaClass脚本起名字,非常重要
    4.点击ok,完成

android 振动权限 安卓震动api_android 振动权限_09

  • 编写Java脚本
    1.打开刚刚建立的脚本,直接复制粘贴我的脚本就好,代码中就必要的注释.
    2.这里我们通过Java的反射原理来获取本来导入class.jar类才能引用到的com.unity3d.player.UnityPlayer包下的currentActivity上下文。同理给unity发消息也是反射原理。「getActivity」和「callUnity」这两个方法,有一定的开发经验应该很容易理解。
    3.这里我们实现两个个简单的接口「showToast」实现简单的文本通信,「showToastShake」实现自定义震动。
    4.以下为代码
package com.carol.a2ulibrary;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Service;
import android.os.Vibrator;
import  android.widget.Toast;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * Created by Admin on 2019/12/21.
 */


public class Android2U {

    /**
     * unity项目启动时的的上下文
     */
    private Activity _unityActivity;
    private Vibrator mVibratorone;//声明一个振动器对象
    /**
     * 获取unity项目的上下文
     * @return
     */
    Activity getActivity(){
        if(null == _unityActivity) {
            try {
                Class<?> classType = Class.forName("com.unity3d.player.UnityPlayer");
                Activity activity = (Activity) classType.getDeclaredField("currentActivity").get(classType);
                _unityActivity = activity;
            } catch (ClassNotFoundException e) {

            } catch (IllegalAccessException e) {

            } catch (NoSuchFieldException e) {

            }
        }
        return _unityActivity;
    }

    /**
     * 调用Unity的方法
     * @param gameObjectName    调用的GameObject的名称
     * @param functionName      方法名
     * @param args              参数
     * @return                  调用是否成功
     */
    boolean callUnity(String gameObjectName, String functionName, String args){
        try {
            Class<?> classType = Class.forName("com.unity3d.player.UnityPlayer");
            Method method =classType.getMethod("UnitySendMessage", String.class,String.class,String.class);
            method.invoke(classType,gameObjectName,functionName,args);

            return true;
        } catch (ClassNotFoundException e) {

        } catch (NoSuchMethodException e) {

        } catch (IllegalAccessException e) {

        } catch (InvocationTargetException e) {

        }
        return false;
    }
    //震动函数

    public void ClickShake(String content)
    {
        Toast.makeText(getActivity(),content,Toast.LENGTH_SHORT).show();
        mVibratorone = (Vibrator)getActivity().getSystemService(Service.VIBRATOR_SERVICE);
        mVibratorone.vibrate(new long[]{0,50},-1);//自定义震动模式,只震动一次
    }

    /**
     * Toast显示unity发送过来的内容
     * @param content           消息的内容
     * @return                  调用是否成功
     */
    public boolean showToast(String content){
        Toast.makeText(getActivity(),content,Toast.LENGTH_SHORT).show();
        //这里是主动调用Unity中的方法,该方法之后unity部分会讲到
        callUnity("Canvas","FromAndroid", "hello unity i'm android");
       // ClickShake();
        return true;
    }
   public boolean showToastShake(String content){

       ClickShake(content);
       return true;
   }

}
  • 设置震动权限

1.打开自己的模块

2.修改xml文件

3.添加权限

android 振动权限 安卓震动api_unity_10

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.carol.a2ulibrary">
    <uses-permission android:name="android.permission.VIBRATE"/>
</manifest>
  • 导出arr文件
    1.点击自己的模块a2ulibrary
    2.点击工具栏的Build
    3.点击Rebuild Project
    4.等待arr包生成完成
  • 找到arr文件给Unity

1.右键自己创建的模块

2.点击Show in Explorer,打开文件位置

3.按路径找到arr文件, XXX\a2ulibrary\build\outputs\aar

4.把arr文件导入Unity项目即可

android 振动权限 安卓震动api_android_11


android 振动权限 安卓震动api_手机震动_12

Unity部分

  • 创建Unity工程
    1.起好工程名字
    2.点击创建工程
    3.创建好工程
  • android 振动权限 安卓震动api_unity_13


  • android 振动权限 安卓震动api_android 振动权限_14

  • 将arr文件导入Unity
    1.创建目录Assets/Plugins/Android,并将刚才导出的arr文件放到该文件夹下,我们的导入就算完成了。没错就是这么Easy,然后我们看看怎么来调用它。
  • android 振动权限 安卓震动api_unity_15

  • 给Unity工程添加对象

1.创建Button
2.设置摄像机属性,设置分辨率
3.调整Button位置
4.修改Button的text的内容
5.复制Button,调整位置及内容
6.添加Text对象

android 振动权限 安卓震动api_android 振动权限_16


android 振动权限 安卓震动api_手机震动_17

android 振动权限 安卓震动api_unity_18

android 振动权限 安卓震动api_unity_19

android 振动权限 安卓震动api_android 振动权限_20


android 振动权限 安卓震动api_android_21

  • 给Unity工程添加脚本
    1.创建C#脚本
    2.将C#脚本挂载到Canvas上.
  • 编写Unity脚本
    1.复制我的脚本的内容即可
using UnityEngine;
using UnityEngine.UI;

public class ASTOUShake : MonoBehaviour
{

    /// <summary>
    /// 场景上的文本框用来显示android发送过来的内容
    /// </summary>
    Text text;
    Button btn_Shake;
    Button btn_ClickMe;

    /// <summary>
    /// android原生代码对象
    /// </summary>
    AndroidJavaObject _ajc;

    void Start()
    {
        text = transform.Find("Text").GetComponent<Text>();
        btn_Shake = transform.Find("Shake").GetComponent<Button>();
        btn_ClickMe = transform.Find("ClickMe").GetComponent<Button>();

        //通过该API来实例化导入的arr中对应的类
        _ajc = new AndroidJavaObject("com.carol.a2ulibrary.Android2U");

        btn_ClickMe.onClick.AddListener(OnBtnClick);
       btn_Shake.onClick.AddListener(OnBtnSkake);

    }

    void Update()
    {

    }

    /// <summary>
    /// 场景上按点击时触发该方法
    /// </summary>
    public void OnBtnClick()
    {
        //通过API来调用原生代码的方法
        bool success = _ajc.Call<bool>("showToast", "this is unity");
        if (true == success)
        {
            //请求成功
            btn_ClickMe.GetComponentInChildren<Text>().text = "龙";
        }
    }

    public void OnBtnSkake()
    {

        //通过API来调用原生代码的方法
        bool success = _ajc.Call<bool>("showToastShake", "这是unity");
        if (true == success)
        {
            //请求成功
            btn_Shake.GetComponentInChildren<Text>().text = "虎";
        }


    }

    /// <summary>
    /// 原生层通过该方法传回信息
    /// </summary>
    /// <param name="content"></param>
    public void FromAndroid(string content)
    {
        text.text = content;
    }
}
  • 打包并发布
    1.点击右上角的File,选择BuildSettings
    2.在弹出窗口选择 Android
    3.点击PlayerSettings
    4.修改公司名称
    5.修改包名
    6.点击Build打包
    7.将apk包发送到安卓手机上

测试

  • 然后打包APK到我们的Android设备上进行测试

android 振动权限 安卓震动api_安卓与unity通信_22

android 振动权限 安卓震动api_手机震动_23

android 振动权限 安卓震动api_android_24

工程源码

百度网盘地址:
链接:https://pan.baidu.com/s/1s5nDUjX0TpHGlTSSS2sBjg
提取码:ncy8
复制这段内容后打开百度网盘手机App,操作更方便哦

PS:注意事项

震动函数

mVibratorone.vibrate(new long[]{0,50},-1);//自定义震动模式,只震动一次

long[]{0,50},大括号里面的参数可以多写几个, 奇数位代表等待时长,偶数位代表震动时长, 时长单位都是ms。 {0, 50,100,40}就表示 等待0ms,震动50ms,再等待100ms,震动40ms。

打包arr
打包arr文件 点击 Rebuild project时, 放置arr文件的文件夹应当关闭,否则会打包失败。

接第三方库
可以在moudle下对接,并打包aar给Unity使用。切记jar需要放到aar的libs下引用,才可以在打包的时候一并导出。通过gradle的网络下载编译方式是不会被打包到aar中的。gradle网络下载的文件的jar可以自行百度查看如何找到。