简体   繁体   中英

C# SerialPort EventHandler in Unity

I am writing C# code for Unity. Just reading SerialPort value in EventHandler. The problem is that the handler is not called. here's the code

using UnityEngine;
using System.Collections;
using System;
using System.IO.Ports;

public class MainScript : MonoBehaviour {

public SerialPort mySerialPort;
public static float speed=100;
GameObject cube ;
public GUIStyle style ;
// Use this for initialization
void Start () {

    cube = GameObject.FindGameObjectWithTag ("cube");

    if(mySerialPort.IsOpen)
        mySerialPort.Close();

    mySerialPort = new SerialPort("com5");
    mySerialPort.BaudRate = 9600;
    mySerialPort.Parity = Parity.None;
    mySerialPort.StopBits = StopBits.None;
    mySerialPort.DataBits = 8;
    mySerialPort.Handshake = Handshake.None;
    mySerialPort.DataReceived += new SerialDataReceivedEventHandler (DataReceivedHandler);

    if(mySerialPort.IsOpen == false)
        mySerialPort.Open();
}


void OnGUI(){
    GUI.Box (new Rect(100,100,100,100),"Speed : " + speed , style);
}
// Update is called once per frame
void Update () {
// speed = mySerialPort.ReadTo ("\r");
// update My View with the speed new value

    cube.transform.Rotate(Vector3.up * speed *Time.deltaTime);

}


public static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
    SerialPort sp = (SerialPort)sender;
    speed = float.Parse( sp.ReadTo ("\r") ) ;
    print ("Data Recieved : " + speed);
}
}

the problem is not in the serial port as, when i read it in the update function for unity it reads the right value but, there's a performance issue updating the UI.

thanks

As you said, the handler for 'DataReceived' event would not be called and it's a known issue with Unity (as of today). My workaround was to use a separate thread to read the port (polling):

private bool _looping;
private SerialPort _port;
public string _comPort; // e.g. "COM3"
private const int _baudRate = 921600;
private Thread portReadingThread;
private string strData;

private void OnEnable()
{
    _looping = true;
    portReadingThread = new Thread(ReadArduino);
    portReadingThread.Start();
}

private void OnDestroy()
{
    _looping = false;  // This is a necessary command to stop the thread.
                       // if you comment this line, Unity gets frozen when you stop the game in the editor.                           
    portReadingThread.Join();
    portReadingThread.Abort();
    _port.Close();
}

void ReadArduino()
{        
    // For any COM number larger than 9, you should add prefix of \\\\.\\ to it. 
    // For example for COM15, you should write it as "\\\\.\\COM15" instead of "COM15".
    _port = new SerialPort(_comPort, _baudRate);
    if (_port == null)
    {
        Debug.LogError("_port is null");
        return;
    }

    _port.Handshake = Handshake.None;
    _port.DtrEnable = true;
    //myPort.RtsEnable = true;
    _port.ReadTimeout = 500; // NOTE: Don't Reduce it or the communication might break!
    _port.WriteTimeout = 1000;
    _port.Parity = Parity.None;
    _port.StopBits = StopBits.One;
    _port.DataBits = 8;
    _port.NewLine = "\n";

    _port.Open();
    if (!_port.IsOpen)
        print("PORT HAS NOT BEEN OPEN!");
    // Send "START" command to the arduino.
    _port.WriteLine("START");
    // Start reading the data coming through the serial port.
    while (_looping)
    {
        strData = _port.ReadLine(); // blocking call.
        print(strData);
        Thread.Sleep(0);
    }
}

The reading happens in the following line:

strData = _port.ReadLine(); // blocking call.

but it does not block or freeze unity because it's happening in a separate thread.

By the way, if you wanted to write something to the port, simply write:

  public void WriteToArduino()
  {
        _port.WriteLine("YourMessageHere");
  }

You can call WriteToArduino() anywhere in your game. It does not need to be in any special thread or something.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM