最近作ってたゲームがある程度できたのでQiitaを書くいい機会だと思い投稿しました。
##どんなゲームを作ったか
ハードウェアを使ったスマホアプリを作りたかったので
チームで話し合った結果、イケメンで女の子を釣るゲームになりました
担当した箇所はBLEを使ったゲームとデバイス間の通信部分を担当しました。
####参照ツイート
https://twitter.com/riti_daichizaki/status/968517033594839040
画像はゆるドラシルの画像を使わせていただきました。
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するためのスクリプトを書きました。
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に対応して欲しいと感じました