您现在的位置是:网站首页> C#技术

Unity3D 框架技术收集

摘要

Unity3D 框架技术收集

Unity3D UI框架

Unity实现Android源生平台蓝牙BLE4.0数据传输(一)

Unity实现Android源生平台蓝牙BLE4.0数据传输(二)

Unity实现Android源生平台蓝牙BLE4.0数据传输(三)




Unity3D UI框架

直接使用NGUI或UGUI

1.Unity-UI-Framework的设计与实现 By:王选易 Github

2.简单、强大的TTUIFramework By:chiuan 游戏蛮牛 (这位的设计思路是参考上面那位作者的)

3.【设计和开发一套自动化UI框架】 By:NPC燕 游戏蛮牛



Unity实现Android源生平台蓝牙BLE4.0数据传输(一)

Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。虽然是游戏引擎,不过现在目前还有很多用来做AR、VR、MR等内容.这样就少不了要与智能硬件配合交互,智能硬件由于便利性都大多数采用无线连接,无线连接主流一般是WIFI、Bluetooth蓝牙等方式.其中蓝牙BLE4.0以更省电、成本低、3毫秒低延迟、超长有效连接距离、AES-128加密等优势,取得大家的青睐,今天就来说说用Unity实现BLE4.0的数据传输.



Unity想要使用Android源生控件或者功能首先我们要来了AndroidJavaClass、AndroidJavaObject、AndroidJavaProxy三个类.


其中 AndroidJavaClass 一般调用静态函数跟获取静态字段使用这个,如果做过unity 跟android交互的朋友们应该见过这句


unityActivity = new AndroidJavaClass("com.unity3d.player.UnityPlayer").GetStatic<AndroidJavaObject>("currentActivity");

这里先new了一个 AndroidJavaClass对象然后调用GetStatic获取静态字段currentActivity


AndroidJavaObject 一般是Java实例对象用来调用Java的实例函数跟获取实例字段.


比如 我要建立一个Java的String对象


 AndroidJavaObject javaString = new AndroidJavaObject("java.lang.String", text); 

我再获取这个String对象的字符长度


var sLenth = javaString.Call<int>("length");

AndroidJavaProxy 是用来实现Java的接口interface. 这里引用Unity官方文档样例



private static DateTime selectedDate = DateTime.Now; 

 public class DateCallback : AndroidJavaProxy

 {

        public DateCallback() :base("android.app.DatePickerDialog$OnDateSetListener") { }

 

        void onDateSet(AndroidJavaObject view, int year, int monthOfYear, int dayOfMonth)

        {

            selectedDate = new DateTime(year, monthOfYear + 1, dayOfMonth);

        }

 }

实现接口以后Android 调用接口函数的时候会调用Unity端的接口实现.但函数名应该保持与Java接口函数一致.



其实能使用AndroidJavaClass、AndroidJavaObject 类已经能使用Android 大部分功能.



Unity实现Android源生平台蓝牙BLE4.0数据传输(二)

这篇我们来利用这些知识来实现蓝牙设备的打开系统功能,扫描,以及连接.


首先想要Android平台使用蓝牙的功能那么权限是不能少的


我们把AndroidManifest.xml文件放在Unity工程的Plugins->Android 文件夹下

1.png

AndroidManifest文件中加入如下代码



  <uses-permission android:name="android.permission.BLUETOOTH" />

  <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

保存之后就可以开始了

首先判断系统的蓝牙是否打开



  var bluetooth = new AndroidJavaClass("android.bluetooth.BluetoothAdapter");//获得Android BluetoothAdapter类

 

  bluetoothAdapter = bluetooth.CallStatic<AndroidJavaObject>("getDefaultAdapter");//获取本地蓝牙设备也就是手机的蓝牙

//判断系统蓝牙是否打开  

if (!bluetoothAdapter.Call<bool>("isEnabled"))

{

var isOpen = bluetoothAdapter.Call<bool>("enable");  //打开蓝牙,需要BLUETOOTH_ADMIN权限  

}



执行之后手机上面会出现android源生的蓝牙打开请求界面 我们选择"是"打开


打开设备后就开始扫描蓝牙设备了



 var mBluetoothLeScanner = bluetoothAdapter.Call<AndroidJavaObject>("getBluetoothLeScanner");

        ScanCallback scanCallback = new ScanCallback();//unity继承的扫描对象接口实现类

        AndroidJavaObject wfzScanCallback = new AndroidJavaObject("com.wfz.bletounity.WFZScanCallback");//蓝牙扫描回调对象

         //扫描结果的事件委托实现

        scanCallback.onScanResultDelegate = (t, r) =>

        {

            if (r == null)

            {

                return;

            }

            var bluetoothDevice = r.Call<AndroidJavaObject>("getDevice");//从结果中获取到设备对象

            var deviceName = bluetoothDevice.Call<string>("getName");//获取设备的名字

            var deviceAddress = bluetoothDevice.Call<string>("getAddress");//获取设备的MAC地址

            Debug.Log("扫描到设备:" + deviceName + "地址:" + deviceAddress);

         

                if (deviceName =="CAD")//判断是否想要的连接的设备名字

                {

                    if (buetoothGatt == null)

                    {

                        ConnectGatt(bluetoothDevice);//连接想要的设备

                        mBluetoothLeScanner.Call("stopScan", wfzScanCallback);//停止扫描

                    }

                }

           

        };

 

        wfzScanCallback.Call("AddUnityCallback", scanCallback);//添加unity对android蓝牙的监听事件

        mBluetoothLeScanner.Call("startScan", wfzScanCallback);//开始扫描

这样我们就连接到我们想要的设备了 下一篇我们来说说数据的获取.



Unity实现Android源生平台蓝牙BLE4.0数据传输(三)

AndroidJavaObject wfzBluetoothGattCallback = new AndroidJavaObject("com.wfz.bletounity.WFZBluetoothGattCallback”);//连接的事件回调对象

        BluetoothGattCallback bluetoothGattCallback = new BluetoothGattCallback();//unity事件回调接口的实现类

//特征值数据变化的事件委托

        bluetoothGattCallback.onCharacteristicChangedDelegate = (g, c) =>

        {

            var data = c.Call<byte[]>("getValue");

            string d = "";

            for (int i = 0; i < data.Length; i++)

            {

                d += data[i];

            }

            Debug.Log(d);

        };

//设备连接状态变化的事件委托

        bluetoothGattCallback.onConnectionStateChangeDelegate = (g, s, n) =>

        {

            switch (n)

            {

                case 0:

                    Debug.Log("断开连接");

                    break;

                case 1:

                    Debug.Log("连接中");

                    break;

                case 2:

                    Debug.Log("连接成功");

                    Debug.Log("获取到gatt对象"+g.Call<AndroidJavaObject>("getDevice").Call<string>("getName"));

                   var isFind= g.Call<bool>("discoverServices");

                    break;

                case 3:

                    Debug.Log("断开中");

                    break;

                default:

                    break;

            }

        };

//发现设备服务事件委托

        bluetoothGattCallback.onServicesDiscoveredDelegate = (g, c) =>

        {

          var  gattServices = g.Call<AndroidJavaObject>("getServices");

            Debug.Log("发现新服务..." + gattServices.Get<int>("size"));

            if (gattCharacteristic==null)

            {

                gattCharacteristic = GetCharacteristic(GetService(g, serviceID), characteristicID);

                NotificationData(g, gattCharacteristic, descriptorID);

            }

        };

回调对象写好了我们就可以连接设备了


wfzBluetoothGattCallback.Call("AddUnityCallback", bluetoothGattCallback);//把实现的接口添加到回调对象

        buetoothGatt = device.Call<AndroidJavaObject>("connectGatt", AndroidCall.unityActivity, true, wfzBluetoothGattCallback);//开始连接

下面是获取服务 特征值的函数实现

  /// <summary>

    /// Gets the service.

    /// </summary>

    /// <returns>The service.</returns>

    /// <param name="gatt">Gatt.</param>

    /// <param name="uuid">UUID.</param>

    public AndroidJavaObject GetService(AndroidJavaObject gatt, string uuid)

    {

        return gatt.Call<AndroidJavaObject>("getService", ToAndroidUUID(uuid));

    }

 

    /// <summary>

    /// Gets the characteristic.

    /// </summary>

    /// <returns>The characteristic.</returns>

    /// <param name="Service">Service.</param>

    /// <param name="uuid">UUID.</param>

    public  AndroidJavaObject GetCharacteristic(AndroidJavaObject Service,string uuid)

    {

        return Service.Call<AndroidJavaObject>("getCharacteristic", ToAndroidUUID(uuid));

    }



打开特征值的通知

  /// <summary>

    /// Notifications the data.

    /// </summary>

    /// <param name="gatt">Gatt.</param>

    /// <param name="characteristic">Characteristic.</param>

    /// <param name="uuid">UUID.</param>

    public void NotificationData(AndroidJavaObject gatt,AndroidJavaObject characteristic,string uuid)

    {

        var b = gatt.Call<bool>("setCharacteristicNotification", characteristic, true);

        if (b)

        {

            var bluetoothGattDescriptor = new AndroidJavaClass("android.bluetooth.BluetoothGattDescriptor");

            var descriptor= characteristic.Call<AndroidJavaObject>("getDescriptor",ToAndroidUUID(uuid));

 

            var  isSet=  descriptor.Call<bool>("setValue", bluetoothGattDescriptor.GetStatic<byte[]>("ENABLE_NOTIFICATION_VALUE"));

            if (isSet)

            {

                var iSwrite=  gatt.Call<bool>("writeDescriptor", descriptor);

                if (iSwrite)

                {

                    Debug.Log("打开特性通知");

                }

            }

        }

    }

打开通知之后 就可以在onCharacteristicChanged 事件里面获取到发送过来的数据了






















Top