Android与Unity交互及手机震动控制

背景

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
    在这里插入图片描述

  • 编写AndroidStudio工程信息
    1.application name 随意,后面也不会用这个工程
    2.存放在合适的位置,记下来之后要找到文件
    3.点击下一步Next
    在这里插入图片描述

  • AndroidStudio工程配置
    1.API的档位尽可能小,能用就行
    2.其它部分不用管
    3.点Next下一步
    在这里插入图片描述

  • 创建空的Activity
    在这里插入图片描述
    直接下一步
    在这里插入图片描述

  • 添加自己的模块

1.在右上角选择为Android
2.右键app选择New
3.点击Module模块
在这里插入图片描述

  • 设置自己的模块

1.选择Android Library
2.点击Next下一步
3.填写Library的名称,这个名称很重要
4.点击Finish完成
在这里插入图片描述

在这里插入图片描述

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

在这里插入图片描述

  • 编写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.添加权限在这里插入图片描述

<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项目即可
在这里插入图片描述
在这里插入图片描述

Unity部分

  • 创建Unity工程
    1.起好工程名字
    2.点击创建工程
    3.创建好工程
    在这里插入图片描述
    在这里插入图片描述

  • 将arr文件导入Unity
    1.创建目录Assets/Plugins/Android,并将刚才导出的arr文件放到该文件夹下,我们的导入就算完成了。没错就是这么Easy,然后我们看看怎么来调用它。
    在这里插入图片描述

  • 给Unity工程添加对象

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

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  • 给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设备上进行测试

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

工程源码

百度网盘地址:
链接: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可以自行百度查看如何找到。

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: AndroidUnity之间的交互可以实现在Unity运行时,调用Android原生代码来实现一些功能。在Android端可以使用 Android Java API 调用 Unity 的代码。而在Unity端,可以使用 C# 代码来调用 Android 的 Java API。这种双向调用可以实现一些比较复杂的跨平台应用,例如在Unity中展示Android硬件设备的信息或者调用相机、传感器等硬件设备来实现某些功能。 例如,在Android端上获取某个传感器的数据,然后传到Unity中,就可以借助Java Native Interface(JNI)来实现。具体实现方式如下: 1. Android端: * 创建一个Native方法,在其中读取传感器数据; * 创建一个Java类,将该Native方法和Unity相关的方法绑定; * 在Unity中调用Java类中的方法,以获取传感器数据。 2. Unity端: * 在C#代码中,调用Android的Java API,以实现数据传输; * 实现Unity的渲染逻辑,以展示从Android端传输过来的数据。 需要注意的是,为了确保代码的正确性和稳定性,一定要在调用之前做好详细的测试工作。 ### 回答2: AndroidUnity是两个流行的软件开发平台,它们都具有广泛的应用。将它们结合起来,可以为应用开发者带来无限的可能性。 在androidunity交互过程中,最主要的问题是如何将android中的数据传递到unity中。这主要分为两种情况:一种是在Unity中使用安卓API(Java代码),另一种是安卓使用Unity中的可编程元素(C#代码)。 在第一种情况下,可以使用Unity的Java接口来实现,编写类似于以下的Java代码: ``` UnityPlayer.UnitySendMessage("GameObjectName", "MethodName", "Message"); ``` 其中,UnitySendMessage方法将消息发送给Unity中的一个GameObject,它接受两个参数,分别是接受消息的对象名和它上面的方法名。 在第二种情况下,可以使用Unity的C#接口来实现。我们可以使用Unity中的SendMessage或BroadcastMessage方法来向Unity对象发送消息(这些对象必须具有MonoBehaviour脚本,否则将不会工作)。 在Android中使用Unity对象也同样简单。我们需要做的就是在Android项目中添加UnityPlayerActivity类,在此类中使用UnityPlayer类的相关方法调用Unity导出的API。 综上所述,将安卓Unity结合起来,可以极大地扩展应用的功能性,并为用户提供更好的体验。通过上述方法可以轻松实现androidunity交互。 ### 回答3: AndroidUnity交互是现在游戏开发中非常常见的一种技术,Android作为手机操作系统的代表,提供了丰富多彩的开发接口,而Unity作为一款游戏引擎,具有着强大的游戏制作功能。两者合作可以大大提高游戏的交互性和玩法。下面我们来分别了解一下AndroidUnity之间的交互方式。 首先是从AndroidUnity交互。由于Android系统是Java语言开发的,而Unity则是C#开发的,所以两者之间实现交互还需要一些中间的桥梁。目前比较常用的方式是通过JNI接口,将Java层面的信息传递到C#层面的Unity中。在Java中,你需要先获取UnityPlayer的实例,然后就可以通过UnityPlayer的方法来调用C#端的函数。具体流程如下: 1. 在Unity中编写对应的C#函数,该函数必须使用静态修饰符(static)。例如: public static void UnityMethod(string str){ Debug.Log("接收到的数据为:" + str); } 2. 在Java中,使用JNI接口调用C#函数。例如: // 获取UnityPlayer实例 UnityPlayer player = new UnityPlayer(); // 调用C#函数 player.UnitySendMessage("GameObject名字", "函数名字", "传递的参数"); UnitySendMessage方法中,第一个参数表示的是GameObject的名字,第二个参数表示的是C#函数的名字,第三个参数就是传递的参数。 其次是从UnityAndroid交互。在Unity中,通过AndroidJavaClass和AndroidJavaObject等API,可以实现调用Java层面的方法。具体流程如下: 1. 在Java中,编写需要调用的方法,这里的方法必须是public静态的。例如: public static void showAndroidToast(String msg){ Toast.makeText(context, msg, Toast.LENGTH_SHORT).show(); } 2. 在Unity中,使用AndroidJavaClass和AndroidJavaObject等API来调用Java方法。例如: // 设置Context AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"); // 调用Java方法 AndroidJavaClass cls = new AndroidJavaClass("com.example.androidTest.MainActivity"); cls.CallStatic("showAndroidToast", currentActivity, "传递的参数"); CallStatic方法中,第一个参数表示要调用的Java层面类的名称,第二个参数表示要调用的Java方法名称,接下来的参数就是要传递的参数。 综上所述,通过JNI和AndroidJavaClass等APIAndroidUnity之间可以很方便地进行交互,相互传递数据和调用各自的方法。这样就能够更好地完成游戏逻辑和UI界面的制作。同时,这种交互方式也为跨平台的开发提供了很好的经验和方法。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值