LoginSignup
20
14

More than 5 years have passed since last update.

Unityで自作デバイスを使ったモバイルアプリを作った話

Posted at

最近作ってたゲームがある程度できたのでQiitaを書くいい機会だと思い投稿しました。

どんなゲームを作ったか

ハードウェアを使ったスマホアプリを作りたかったので
チームで話し合った結果、イケメンで女の子を釣るゲームになりました
担当した箇所はBLEを使ったゲームとデバイス間の通信部分を担当しました。

参照ツイート

IMG_2284.PNGIMG_2285.PNGIMG_2287.PNG

画像はゆるドラシルの画像を使わせていただきました。
http://yurudora.com/tkool/

開発環境

Unity

今回の話のメイン

UnityのスマホアプリでBLEを使った開発の記事がほぼ皆無かつ
今回使ったAssetの日本語での解説が皆無なため
自分へのメモを兼ねて書きます。

1.今回使ったAssetの紹介

Bluetooth LE for iOS, tvOS and Android

iOS,tvOS,Androidに対応してBLE通信用Assetです。
とても安価なのでPlugin開発が面倒な場合とてもオススメです。

2.実装

今回のAssetは突っ込んだらそのまま使えるなどの仕様ではなかっため
サンプルを参考にperipheralからreadするためのスクリプトを書きました。

qiita.c#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class BLEManager : MonoBehaviour{
    enum States{
        None,
        Scan,
        ScanRSSI,
        Connect,
        Read,
        Disconnect
    }

    public string   DeviceName          = "デバイスの名前";
    string          ServiceUUID         = "サービスUUID";
    string          ReadCharacteristic  = "キャラクタリスティックUUID";

    BluetoothDeviceScript bds;

    string _message;

    public string GetMessage(){
        return _message;
    }

    private bool _connected = false;
    private float _timeout = 10f;
    private States _state = States.None;
    private string _deviceAddress;
    private bool _foundReadID = false;
    private byte[] _dataBytes = null;
    private bool _rssiOnly = false;
    private int _rssi = 0;


    // Use this for initialization
    void Start(){
        BluetoothLEHardwareInterface.Initialize(true, false, () =>{

            SetState(States.Scan, 0.1f);

        }, (error) =>{

            BluetoothLEHardwareInterface.Log("Error during initialize: " + error);
        });

        bds = GameObject.Find("BluetoothLEReceiver").GetComponent<BluetoothDeviceScript>();

    }

    // Update is called once per frame
    void Update(){
        if (_timeout > 0f){
            _timeout -= Time.deltaTime;
            if (_timeout <= 0f){
                _timeout = 0f;

                switch (_state){
                    case States.None:
                        break;

                    case States.Scan:
                        BluetoothLEHardwareInterface.ScanForPeripheralsWithServices(null, (address, name) =>{

                            if (!_rssiOnly){
                                if (name.Contains(DeviceName)){
                                    BluetoothLEHardwareInterface.StopScan();

                                    _deviceAddress = address;
                                    SetState(States.Connect, 0.5f);
                                }
                            }

                        }, (address, name, rssi, bytes) =>{

                            if (name.Contains(DeviceName)){
                                if (_rssiOnly){
                                    _rssi = rssi;
                                }
                                else{
                                    BluetoothLEHardwareInterface.StopScan();

                                    // found a device with the name we want
                                    // this example does not deal with finding more than one
                                    _deviceAddress = address;
                                    SetState(States.Connect, 0.5f);
                                }
                            }

                        }, _rssiOnly); // this last setting allows RFduino to send RSSI without having manufacturer data

                        if (_rssiOnly)
                            SetState(States.ScanRSSI, 0.5f);
                        break;

                    case States.ScanRSSI:
                        break;

                    case States.Connect:
                        _foundReadID = false;

                        BluetoothLEHardwareInterface.ConnectToPeripheral(_deviceAddress, null, null, (address, serviceUUID, characteristicUUID) =>{
                            BluetoothLEHardwareInterface.Log("connectToPeripheral");


                            if (IsEqual(serviceUUID, ServiceUUID)){
                                _foundReadID = _foundReadID || IsEqual(characteristicUUID, ReadCharacteristic);

                                if (_foundReadID){
                                    _connected = true;
                                    SetState(States.Read, 2f);
                                }
                            }
                        });
                        break;
                    case States.Read:
                        BluetoothLEHardwareInterface.ReadCharacteristic(_deviceAddress, ServiceUUID, ReadCharacteristic, (message, messageChar) =>{
                            _message = bds._message;
                        });

                        _timeout = 0.1f;

                        break;

                    case States.Disconnect:
                        if (_connected){
                            BluetoothLEHardwareInterface.DisconnectPeripheral(_deviceAddress, (address) =>{
                                BluetoothLEHardwareInterface.DeInitialize(() =>{

                                    _connected = false;
                                    _state = States.None;
                                });
                            });
                        }
                        else
                        {
                            BluetoothLEHardwareInterface.DeInitialize(() => {

                                _state = States.None;
                            });
                        }
                        break;
                }
            }
        }
    }

    bool IsEqual(string uuid1, string uuid2){
        if (uuid1.Length == 4)
            uuid1 = FullUUID(uuid1);
        if (uuid2.Length == 4)
            uuid2 = FullUUID(uuid2);


        return (uuid1.CompareTo(uuid2) == 0);
    }

    string FullUUID(string uuid){
        return "0000" + uuid + "-0000-1000-8000-00805f9b34fb";
    }

    void SetState(States newState, float timeout){
        _state = newState;
        _timeout = timeout;
    }
}

他のオブジェクトからGetCompornetするとかしてGetMessage()を実行してあげると
メッセージを取得することができます。

終わりに

BLEを使った開発はSwiftとか書くのは楽なのですが、
Unityを使った場合はPlugin依存なってしまいます。
しかも情報がほぼ皆無。

Unityの可能性はまだまだあると思うので公式でもっとIotに対応して欲しいと感じました

20
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
14