UUNITY3D插件InControl的简单使用_安卓端连接蓝牙手柄

由于项目需要,要在安卓端连接蓝牙手柄,找了一个unity上专门用来处理手柄连接的插件InControl,网上找了一圈,教程都很不明确,花了一点时间研究了一下,顺便封装了一下,在这记录一下。

InControl: Introduction - Gallant Games  http://www.gallantgames.com/pages/incontrol-introduction

这个是这个插件在gallantgames上面的地址,有一些介绍和入门教程,有兴趣可以去看一下,这个插件有很多适用场合,这里不多做介绍,只说安卓上面的连接。

我用的蓝牙手柄是基于HID协议的,通过一点映射对照,下面是一些简单的映射关系:

         

以上是基于HID协议的手柄映射情况,其他手柄可以使用插件提供的一个test测试按键的映射关系。

言归正传,直接进入代码:

按键接受类需要实现的接口

using UnityEngine;
using System.Collections;

/**
 * 按键输入类接收者必须实现的接口
 * */
public interface InputReciverServer{

    void reciveAction(InputTool.INPUT_TYPE type);

}
简单的实现类

using UnityEngine;
using System.Collections;
using InControl;
using UnityEngine.UI;
public class Test2 : MonoBehaviour,InputReciverServer{

    public Text text;
   
    //有按键按下会执行这个方法,参数是按键的类型
    public void reciveAction(InputTool.INPUT_TYPE type) {
        text.text = type.ToString();
    }

}
再来看一下,发送方的抽象类

using UnityEngine;
using System.Collections.Generic;

/**
 * 输入抽象类
 * */
public abstract class InputServer : MonoBehaviour{

	// 保存订阅者列表
	private List<InputReciverServer> recivers = new List<InputReciverServer>();

	//新增对订阅号列表的维护操作
	public void addRecive(InputReciverServer ob)
	{
		recivers.Add(ob);
	}
	public void removeRecive(InputReciverServer ob)
	{
		recivers.Remove(ob);
	}
		
	/**
	 * 通知所有的订阅者
	 * */
    public void broadCast(InputTool.INPUT_TYPE type)
	{
		foreach (InputReciverServer ob in recivers)
		{
			if (ob != null)
			{
				ob.reciveAction(type);
			}
		}
	}

}

然后是主要的部分,也是唯一调用InControl的地方

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using InControl;//使用InControl需要导入

public class InputTool : InputServer{
    //保存InputTool的唯一实例
    public static InputTool inputTool;
    private InputTool() {}

    //保存input接收者的具体游戏对象
    public List<GameObject> reciveGo = new List<GameObject>();

    void Start()
    {
        //注册订阅者
        foreach (var go in reciveGo)
        {
            var irs = go.GetComponents<InputReciverServer>();
            foreach (var ir in irs)
            {
                addRecive(ir);
            }
        }
    }
    //获取InputTool实例的唯一方法
    public static InputTool getInstance() {
        if (inputTool == null)
            inputTool = new InputTool();
        return inputTool;
    }
	
	void Update () {
	    InputDevice id = InputManager.ActiveDevice;
        //左摇杆
        if (id.GetControl(InputControlType.LeftStickLeft))
        {
            broadCast(INPUT_TYPE.LEFT_STICK_LEFT);
        }
        if (id.GetControl(InputControlType.LeftStickRight))
        {
            broadCast(INPUT_TYPE.LEFT_STICK_RIGHT);
        }
        if (id.GetControl(InputControlType.LeftStickUp))
        {
            broadCast(INPUT_TYPE.LEFT_STICK_UP);
        }
        if (id.GetControl(InputControlType.LeftStickDown))
        {
            broadCast(INPUT_TYPE.LEFT_STICK_DOWN);
        }
        //ABXY
        if (id.GetControl(InputControlType.Button0))
        {
            broadCast(INPUT_TYPE.MENU_A);
        }
        if (id.GetControl(InputControlType.Button1))
        {
            broadCast(INPUT_TYPE.MENU_B);
        }
        if (id.GetControl(InputControlType.Button2))
        {
            broadCast(INPUT_TYPE.MENU_X);
        }
        if (id.GetControl(InputControlType.Button3))
        {
            broadCast(INPUT_TYPE.MENU_Y);
        }
        //左方向键
        if (id.GetControl(InputControlType.Analog4).Value < 0)
        {
            broadCast(INPUT_TYPE.DIRECTION_LEFT);
        }
        if (id.GetControl(InputControlType.Analog4).Value > 0)
        {
            broadCast(INPUT_TYPE.DIRECTION_RIGHT);
        }
        if (id.GetControl(InputControlType.Analog5).Value < 0)
        {
            broadCast(INPUT_TYPE.DIRECTION_UP);
        }
        if (id.GetControl(InputControlType.Analog5).Value > 0)
        {
            broadCast(INPUT_TYPE.DIRECTION_DOWN);
        }
        //右摇杆
        if (id.GetControl(InputControlType.Analog2).Value < 0)
        {
            broadCast(INPUT_TYPE.RIGHT_STICK_LEFT);
        }
        if (id.GetControl(InputControlType.Analog2).Value > 0)
        {
            broadCast(INPUT_TYPE.RIGHT_STICK_RIGHT);
        }
        if (id.GetControl(InputControlType.Analog3).Value < 0)
        {
            broadCast(INPUT_TYPE.RIGHT_STICK_UP);
        }
        if (id.GetControl(InputControlType.Analog3).Value > 0)
        {
            broadCast(INPUT_TYPE.RIGHT_STICK_DOWN);
        }

        if (id.GetControl(InputControlType.Button10))
        {
            broadCast(INPUT_TYPE.START);
        }
        if (id.GetControl(InputControlType.Button11))
        {
            broadCast(INPUT_TYPE.SELECT);
        }

	}
    //定义所有的按键类型
    public enum INPUT_TYPE { 
        LEFT_STICK_LEFT,
        LEFT_STICK_RIGHT,
        LEFT_STICK_UP,
        LEFT_STICK_DOWN,

        DIRECTION_LEFT,
        DIRECTION_RIGHT,
        DIRECTION_UP,
        DIRECTION_DOWN,

        RIGHT_STICK_LEFT,
        RIGHT_STICK_RIGHT,
        RIGHT_STICK_UP,
        RIGHT_STICK_DOWN,

        MENU_A,
        MENU_B,
        MENU_X,
        MENU_Y,

        START,
        SELECT
    }

}

上面使用的只是InControl提供的一种获取按键信号的方法,还有更多的方法可以在上面的链接里面查看,接下是在UNITY中具体的使用了

一,设置InControl模式

UNITY菜单点击Edit->Project Setting->InControl->setup就可以设置好了,前提是已经导入了插件

二,创建管理器

GameObject->Create Other->InControl->Manager即可完成创建



三,使用工具,创建空物体,将前面写好的InputTool脚本挂载上去


四,注册成观察者,接收按键事件,将实现了InputReciverServer的脚本挂载到任意物体上,并将该物体托进上面InputTool的Recive Go里面即可,这了可以接受多个观察者


完成以上几步,打包到安卓手机上就可以接受蓝牙手柄的按键事件了,我这边使用了一个Text来显示按键的类型


看一下效果


  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个简单的Flutter页面示例,用于搜索蓝牙设备、连接设备并发送指令。您可以在此基础上进行修改和扩展,以满足您的具体需求。 ```dart import 'package:flutter/material.dart'; import 'package:flutter_blue/flutter_blue.dart'; class BluetoothPage extends StatefulWidget { @override _BluetoothPageState createState() => _BluetoothPageState(); } class _BluetoothPageState extends State<BluetoothPage> { FlutterBlue flutterBlue = FlutterBlue.instance; List<BluetoothDevice> devices = []; BluetoothDevice connectedDevice; bool isConnecting = false; bool isConnected = false; String command = ""; @override void initState() { super.initState(); scanDevices(); } void scanDevices() { flutterBlue.scan(timeout: Duration(seconds: 5)).listen((scanResult) { if (!devices.contains(scanResult.device)) { setState(() { devices.add(scanResult.device); }); } }); } void connectToDevice(BluetoothDevice device) async { setState(() { isConnecting = true; }); await device.connect(); setState(() { isConnecting = false; isConnected = true; connectedDevice = device; }); } void disconnectFromDevice() async { await connectedDevice.disconnect(); setState(() { isConnected = false; connectedDevice = null; }); } void sendCommand() async { List<BluetoothService> services = await connectedDevice.discoverServices(); BluetoothCharacteristic characteristic; for (BluetoothService service in services) { for (BluetoothCharacteristic c in service.characteristics) { if (c.uuid.toString() == "YOUR_CHARACTERISTIC_UUID") { characteristic = c; break; } } if (characteristic != null) { break; } } if (characteristic != null) { await characteristic.write(command.codeUnits); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Bluetooth Control"), ), body: Column( children: [ Padding( padding: EdgeInsets.all(16.0), child: Row( children: [ Expanded( child: TextField( decoration: InputDecoration( hintText: "Enter command", ), onChanged: (value) { setState(() { command = value; }); }, ), ), SizedBox(width: 16.0), ElevatedButton( child: Text("Send"), onPressed: () { sendCommand(); }, ), ], ), ), Expanded( child: ListView.builder( itemCount: devices.length, itemBuilder: (context, index) { BluetoothDevice device = devices[index]; return ListTile( title: Text(device.name), subtitle: Text(device.id.toString()), trailing: IconButton( icon: Icon(Icons.bluetooth_connected), onPressed: isConnected ? () { disconnectFromDevice(); } : isConnecting ? null : () { connectToDevice(device); }, ), ); }, ), ), ], ), ); } } ``` 在上面的代码中,我们使用了FlutterBlue插件来搜索、连接和控制蓝牙设备。在页面上,我们使用了一个文本框和一个发送按钮来输入和发送指令,使用一个列表来显示可用的蓝牙设备,并在列表项中添加了一个连接/断开连接按钮。当用户点击连接按钮时,我们会调用`connectToDevice()`方法来连接设备,并在连接成功后更新页面状态。当用户点击断开连接按钮时,我们会调用`disconnectFromDevice()`方法来断开连接,并再次更新页面状态。当用户点击发送按钮时,我们会调用`sendCommand()`方法来发送指令。 请注意,上面的代码仅供参考。具体实现可能因应用需求而异。您需要根据您的具体情况进行修改和扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值