【问题标题】:使用 [ Arduino + 蓝牙模块 (HC-05) ] 或 ESP32 连接 Unity 游戏
【发布时间】:2020-11-09 09:37:17
【问题描述】:

我想通过 蓝牙 将我的 Unity 3D 游戏微控制器Arduino 连接起来我正在使用 (HC-05) 蓝牙模块。

为此,资产商店中有一个名为 Arduino 蓝牙插件 Link 的插件。 收费为 19 美元。

仅使用免费功能编码还有其他方法吗?

【问题讨论】:

  • 有几个数据表和说明如何使用 HC05 和其他蓝牙模块。要将 Unity 连接到您的 COM 端口(这是从模块读取所必需的),请参阅this question。请注意,HC-05 无法连接到所有蓝牙版本(如 iOS)。 This website 可以指导您选择最适合您项目需求的模块。

标签: unity3d arduino bluetooth hc-05


【解决方案1】:

您绝对可以通过自己编写代码来完成。

我无法在 C# 部分为您提供帮助,但我已经编写了代码以通过 HC-06 模块为 arduino 发送数据,并通过蓝牙和蓝牙低功耗与 Android 应用程序进行通信。

归根结底与 Socket 编程非常相似。

所以对于 C# 部分this user has a basic working C# BT communication example

对于 Arduino 方面,我使用了这个草图:


/**************************************************
 * 
 * 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);
  
}

使用此接线:

该模块的图像也可能对您有用,因此您可以看到引脚排列:

因此,在将 arduino 与我的笔记本电脑配对并使用命令收听传入消息后

$ cat /dev/rfcomm0

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

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

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

【讨论】:

    【解决方案2】:

    是的。

    不是 100% 肯定,但我认为蓝牙的工作方式与 USB 连接非常相似。这是 Unity 中适用于 Arduino 的 C# 控制器的示例,适用于 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
    }
    

    有了所有这些信息,您就可以确定蓝牙是否需要任何额外的配置或修改,如果是这种情况,请告诉我们^^

    【讨论】:

      【解决方案3】:

      Arduino 通过 USB 连接到 PC,因此可以通过 Serial I/OPort 访问。您首先需要在统一的Start() 方法中初始化串行并定义端口,以便它可以监听。在我的代码中,我正在从 Update() 方法监听端口。如果您想将input 发送到arduino,请参阅SerialCmdSend(string data) 方法,它将参数作为string 值。您可以根据需要定义它或在 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 文档here 了解更多信息。

      如果您需要进一步的帮助,请告诉我。

      【讨论】:

        猜你喜欢
        • 2022-01-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-02-19
        • 2018-03-10
        • 1970-01-01
        • 2017-07-22
        • 1970-01-01
        相关资源
        最近更新 更多