将Unity游戏与[Arduino + 蓝牙模块(HC-05)]或ESP32连接

5
我想通过(HC-05)蓝牙模块将我的Unity 3D游戏Arduino微控制器连接起来。为此,我使用了名为Arduino Bluetooth Plugin链接的插件,该插件在资产商店中售价19美元
是否有其他方法可以仅使用免费功能编码来完成此操作?

有几份数据手册和Instructables介绍如何使用HC05和其他蓝牙模块。要将Unity连接到您的COM端口(这是从模块读取所必需的),请参见此问题。请注意,HC-05无法连接到所有蓝牙版本(例如iOS)。此网站可以指导您选择最适合项目需求的最佳模块。 - Rojo
3个回答

4
您肯定可以通过自己编写代码来实现它。
对于C#部分,我无法提供帮助,但是我已经编写了代码,可以通过HC-06模块将数据发送到Arduino,并通过蓝牙和蓝牙低功耗与Android应用程序进行通信。
最终与Socket编程非常相似。
因此,对于C#部分, 这个用户提供了一个基本的C#蓝牙通信示例
而对于Arduino方面,我使用了这个sketch:

/**************************************************
 * 
 * Using the BUILT-IN Serial.
 * 
 * CONFIGURATION:
 * 
 *          ARDUINO NANO - HC-06
 *    YELLOW     TX         RX
 *    GREEN      RX         TX
 *    RED        3V3        VCC
 *    BLACK      GND        GND
 * 
 **************************************************/
void setup() {
  // Init the Built-In Serial.
  Serial.begin(9600);
}
void loop() {
  // Send the message
  Serial.println("MISSATGE PER UN LINUX!!!");

  delay(2000);
  
}

使用以下接线方式: 接线 此模块的图像也可能对您有用,这样您就可以看到引脚定义: HC-06 引脚定义 因此,在将Arduino与我的笔记本配对并使用命令侦听传入消息后,
$ cat /dev/rfcomm0

我开始在控制台看到输出:

控制台输出

因此,您可以发送从Arduino输入读取的任何内容,然后在C#端重新解析它,而不是发送字符串。

希望我对您有所帮助;祝您好运!!!


2

没错,确实如此。

虽然不是100%确定,但我认为蓝牙连接与USB连接相似。以下是一个在Unity中使用C#控制Arduino的示例,它可以通过Arduino USB连接工作:

using System;
using System.IO.Ports;
using UnityEngine;
using UnityEngine.UI;

public class ArduinoController : MonoBehaviour
{
    [Header("Messages")]
    [SerializeField] private String m_MessageReaded = "";
    [SerializeField] private String m_MessageSended = "";

    [Header("SerialPort values")]
    [SerializeField] private String m_COM = "COM7";
    [SerializeField] private int m_baudrate = 115200;
    [SerializeField] private int m_readTimeout = 10;
    [SerializeField] private int m_writeTimeout = 10;
    [SerializeField] private float m_delay = 0.05f;
    private SerialPort m_serialPort;
    private float m_lastSentTime;



    //Initialize and open SerialPort, set timers
    void Start()
    {
        m_serialPort = new SerialPort(m_COM, m_baudrate)
        {
            ReadTimeout = m_readTimeout,
            WriteTimeout = m_writeTimeout
        };

        OpenPort(m_serialPort);

        m_lastSentTime = Time.time;
    }

    // Update is called once per frame
    void Update()
    {
        ManageArduinoCommunication();
    }

    //Encapsulated try-catch to open the port
    void OpenPort(SerialPort port)
    {
        try
        {
            port.Open();
            print("Open Port " + port.PortName);

        }
        catch (Exception e)
        {
            print("Do not open Port " + port.PortName);
        }
    }

    public void ManageArduinoCommunication()
    {
        if (m_serialPort != null)
        {
            if (m_serialPort.IsOpen)
            {
                //WRITE TO ARDUINO
                WriteToArduino();

                //READ FROM ARDUINO
                ReadFromArduino();
            }
        }
        else
        {
            OpenPort(m_serialPort);
        }

    }

    private void WriteToArduino()
    {
        m_MessageSended = "";

        if (!Input.GetKeyDown(KeyCode.LeftShift))
        {
            if (Input.GetKeyDown(KeyCode.Alpha2))
            {
                m_MessageSended = "openGate";
                m_serialPort.WriteLine(m_MessageSended);
            }
            if (Input.GetKeyDown(KeyCode.Alpha4))
            {
                m_MessageSended = "closeGate";
                m_serialPort.WriteLine(m_MessageSended);
            }
        }
    }

    private void ReadFromArduino()
    {
        if (Time.time - m_lastSentTime >= m_delay)
        {
            try
            {
                m_MessageReaded = m_serialPort.ReadLine();
            }
            catch (TimeoutException e)
            {
                // no-op, just to silence the timeouts.
                // (my arduino sends 12-16 byte packets every 0.1 secs)
            }
            m_lastSentTime = Time.time;
        }
    }

    private void OnApplicationQuit()
    {
        m_serialPort.Close();
    }
}

那么你需要在Arduino端编写类似于以下代码的代码:
//define PINS
#define DOOR_PIN_OPEN 26
#define DOOR_PIN_OPEN_2 27
#define DOOR_PIN_CLOSE 30
#define DOOR_PIN_CLOSE_2 31   

//declare variables
bool isOpen = false;
String message = ""; 

void setup() {
  //Set pinModes
  pinMode(DOOR_PIN_OPEN,OUTPUT);
  pinMode(DOOR_PIN_OPEN_2,OUTPUT);
  pinMode(DOOR_PIN_CLOSE,OUTPUT);
  pinMode(DOOR_PIN_CLOSE_2,OUTPUT);
  
  //Set initial values
  digitalWrite(DOOR_PIN_OPEN, HIGH);
  digitalWrite(DOOR_PIN_OPEN_2, HIGH);
  digitalWrite(DOOR_PIN_CLOSE, LOW);
  digitalWrite(DOOR_PIN_CLOSE_2, LOW);

  Serial.begin(115200);
}

void loop() {
  if(Serial.available() > 0){
    ReadSensorsStates();
    
    //CheckSerialInputs();
    
    ReadFromUnity();

    UpdateSensorsStates();
  }
  else{
    //Serial.println("not available");  
  }
}

void ReadSensorsStates(){
    //Start the sensors reading
    isOpen = ( digitalRead(DOOR_PIN_OPEN) == LOW );
    
    //Serial.println(isOpen);
}

void CheckSerialInputs(){
}

void ReadFromUnity()
{
    message = Serial.readString();
    message = message.substring(0,message.length() -2); //purge \0\n

    if( message == "openGate" ){
      Serial.println(message);
      delay(500);    
    
      digitalWrite(DOOR_PIN_OPEN, HIGH);
      digitalWrite(DOOR_PIN_CLOSE, LOW);        
    }
    
    if(message == "closeGate"){
      Serial.println(message);
      delay(500); 
      digitalWrite(DOOR_PIN_OPEN, LOW);
      digitalWrite(DOOR_PIN_CLOSE, HIGH);        
    }

    //reset variables
    message = "";  
    delay(200);    
}

void UpdateSensorsStates()
{
  //code to update sensorsStates
}

有了所有这些信息,你肯定能够找出是否需要对蓝牙进行任何额外的配置或修改,如果是这种情况,请告诉我们 ^^


2

Arduino通过USB连接到PC,因此可以通过串行输入/输出端口进行访问。您需要在Unity的Start()方法中初始化串行并定义端口,以便它可以监听。在我的代码中,我从Update()方法中监听端口。如果您想将输入发送到Arduino,请参见SerialCmdSend(string data)方法,该方法以字符串值作为参数。您可以根据需要定义此内容或在Arduino代码中更改。

Unity C# 代码:

using UnityEngine;
using System.Net;
using System.IO;
using System.IO.Ports;
using System;

public class Controller : MonoBehaviour
{
    SerialPort serial = new SerialPort();
    void Start()
    {
        InitializeSerial();
    }

    void InitializeSerial()
    {
        try
        {
            serial.PortName = "Your Port";

            serial.BaudRate = 9600;

            serial.Handshake = System.IO.Ports.Handshake.None;

            serial.Parity = Parity.None;

            serial.DataBits = 8;

            serial.StopBits = StopBits.One;

            serial.ReadTimeout = 20;

            serial.WriteTimeout = 50;

            serial.DtrEnable = true;

            if (!serial.IsOpen)
            {

                serial.Open();

            }
        }

        catch (Exception e)
        {
            print("Error: " + e.Message);
        }
    }

    void Update()
    {
        //check serial
        if (serial.IsOpen)
        {
            try
            {
                //print("serial " + serial.ReadByte());
                if (serial.ReadByte() == 0)
                {
                    //Do something here
                }
                else
                {
                    // Do something else
                }

            }
            catch (Exception e)
            {
                print("Error: " + e.Message);
            }
        }
    }

    public void SerialCmdSend(string data)
    {
        if (serial.IsOpen)
        {
            try
            {
                byte[] hexstring = Encoding.ASCII.GetBytes(data);
                foreach (byte hexval in hexstring)
                {
                    byte[] _hexval = new byte[] { hexval };
                    serial.Write(_hexval, 0, 1);
                    Thread.Sleep(1);
                }

            }

            catch (Exception ex)
            {
                print(ex);
            }

        }
    }
}


   

Arduino代码:

首先在Arduino IDE中检查您的端口,选择工具 >> 端口 >> 您的Arduino连接的端口号,并将此端口复制并粘贴到Unity代码上方。

const int RELAY_PIN1 = 3;
const int RELAY_PIN2 = 4;
const int  buttonPin = 2;       


int buttonPushCounter = 0;   
int buttonState = 0;        
int lastButtonState = 0; 
   
int incomingByte = 0; 
bool onLight = false;

void setup() {
 
  pinMode(buttonPin, INPUT);
  
 
  
  pinMode(RELAY_PIN1, OUTPUT);
   pinMode(RELAY_PIN2, OUTPUT);
  
  Serial.begin(9600);
}


void loop() {
  
  buttonState = digitalRead(buttonPin);
 
  if (buttonState != lastButtonState) {
    
    if (buttonState == HIGH) {
     
      buttonPushCounter++;
      
     
    } 
    if (buttonState == LOW) {
      
        Serial.write(0);
      Serial.flush();
    }
    // Delay a little bit to avoid bouncing
    delay(20);
  }
  // save the current state as the last state, for next time through the loop
  lastButtonState = buttonState;

 if(onLight)
 {
   digitalWrite(RELAY_PIN1, HIGH);
  digitalWrite(RELAY_PIN2, HIGH);
  delay(500);
   digitalWrite(RELAY_PIN1, LOW);
  digitalWrite(RELAY_PIN2, LOW);
  delay(500);
 }
 else
{
    digitalWrite(RELAY_PIN1, LOW);
    digitalWrite(RELAY_PIN2, LOW);
}
 
if (Serial.available() > 0) 
{

   char ltr = Serial.read();
   if(ltr == 'r')
   {
    onLight = true;
   }
   else if(ltr = 'g')
   {
     onLight = false;
   }
 }

这是根据我的需求编写的代码。您完全可以更改它或编写自己的代码。重要的是,您希望如何从Arduino接收输入到Unity。我正在使用Serial.write(0)将输入作为整数值从Arduino接收。您可以通过使用Serial.println("on")将其作为字符串接收。有关更多信息,请查阅Arduino文档这里
如果需要进一步帮助,请告诉我。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接