unity接陀螺仪数据,走的串口,可以通过蓝牙或者usb传输数据。 主要用来控制场景中相机方向,配合一些没有陀螺仪的头盔使用。 关于串口获取数据,本人菜鸟一个,在网上找了一堆资料,最后自己改了一段代码,这篇文章写的比较晚,之前找资料的网址找不到了,如果有版权问题请发消息给我。 本文只取的是维特智能的JY-61的方向,没有取其他两种参数,有需要自己改代码。
点击此处添加图片说明文字
点击此处添加图片说明文字
点击此处添加图片说明文字
代码如下:说明一下,里面注释的一段是网上找的串口消息解析,原作者使用了2中方法解析,我只看懂了笨办法,正则表达式那段代码开不明白,有大神能理解给我留言讲解下吧! using UnityEngine; using System.Collections; using System.Collections.Generic; using System.Threading; using System.IO.Ports; using System; using System.Text; using System.Text.RegularExpressions; public class ReadIO : MonoBehaviour { private Thread tPort; private Thread tPortDeal;//这两个为两个线程,一个是读取串口数据的线程一个是处理数据的线程 bool isStartThread;//控制FixedUpdate里面的两个线程是否调用(当准备调用串口的Close方法时设置为false) SerialPort spstart; public static float angleX; public static float angleY; public static float angleZ; string recData; private byte[] DataBuf; void Start() { DataBuf = new byte[11]; //如果取三组数据:加速度,角速度,角度则byte取长度33,单个取11长度 isStartThread = true; spstart = new SerialPort("COM7", 9600, Parity.None, 8, StopBits.One); try { spstart.Open(); } catch (Exception e) { Debug.Log(e.ToString()); } tPortDeal = new Thread(ReceiveData); tPortDeal.Start(); tPort = new Thread(DealData); tPort.Start(); } void Update() { } void FixedUpdate() { //定期回收垃圾 if (Time.frameCount % 120 == 0) System.GC.Collect(); } //接收数据 // private Queue<string> queueDataPool; private void ReceiveData() { while(isStartThread) { #region try { //读取数据 byte tempB = 0; tempB = (byte)spstart.ReadByte(); //Read the header first if (tempB == 85) //获取包头16进制的55,换算下来就是10进制的85 { DataBuf[0] = tempB; tempB = (byte)spstart.ReadByte(); if (tempB == 83) //获取第二个字节53,换算下是83 { DataBuf[1] = tempB; int DataNumber = 2; while (DataNumber < 11) { tempB = (byte)spstart.ReadByte(); DataBuf[DataNumber] = tempB; DataNumber++; } recData = ToHexString(DataBuf); // Debug.Log(recData); } } // Thread.Sleep(10); } catch (Exception e) { StartCoroutine(ClosePort()); Debug.LogError(e); } #endregion /*try { //从输入缓存区中去读取第一次出现"AA"时的内容 Byte[] buf = new Byte[33]; spstart.Read(buf, 0, 33); //如果没有接到到数据,就返回 if (buf.Length == 0) { return; } string sbReadline2str = string.Empty; if (buf != null) { for (int i = 0; i < buf.Length; i++) { sbReadline2str += buf.ToString("X2"); } } //提取完整的一个数据包,压入数据池中(队列中) if (sbReadline2str.StartsWith("5553")) { sbReadline2str = sbReadline2str.Substring(0, 11); //分组数据包 //string[] _str = Regex.Split(sbReadline2str, "5553", RegexOptions.IgnoreCase); //foreach (string s in _str) //{ // if (s.Length == 31) // { // //数据进入队列 // queueDataPool.Enqueue( "5553"+s); // Debug.LogError("5553" + s); // } //} } else { sbReadline2str = sbReadline2str.Remove(0, sbReadline2str.IndexOf("5553")); if(sbReadline2str.Length >= 11) { sbReadline2str = sbReadline2str.Substring(0, 11); Debug.Log(sbReadline2str); } //string[] _str = Regex.Split(sbReadline2str, "5553", RegexOptions.IgnoreCase); //foreach (string s in _str) //{ // if (s.Length == 31) // { // //数据进入队列 // queueDataPool.Enqueue("5553" + s); // Debug.LogError("5553" + s); // } //} } } catch (Exception ex) { Debug.LogError(ex); }*/ } } //byte转16进制字符串 public static string ToHexString(byte[] bytes) // 0xae00cf => "AE00CF " { string hexString = string.Empty; if (bytes != null) { StringBuilder strB = new StringBuilder(); for (int i = 0; i < bytes.Length; i++) { strB.Append(bytes.ToString("X2")); } hexString = strB.ToString(); } return hexString; } private void DealData() { while (isStartThread) { CalculateAngle(); } } //解析数据,换算成角度。 void CalculateAngle() { if (recData == null) return; //Debug.Log("处理字符: " + recData); /*把16进制字符串转换成字节数组*/ byte[] returnBytes = new byte[recData.Length / 2]; for (int i = 0; i < returnBytes.Length; i++) returnBytes = Convert.ToByte(recData.Substring(i * 2, 2), 16); float _FangXiangJiao = (float)((byte)returnBytes[2] + ((sbyte)returnBytes[3] << 8)) / 32768 * 180; //Debug.Log("x-->" + _FangXiangJiao); float _YangJiao = (float)((byte)returnBytes[4] + ((sbyte)returnBytes[5] << 8)) / 32768 * 180; // Debug.Log("y-->" + _YangJiao); float _XuanZhuanJiao = (float)((byte)returnBytes[6] + ((sbyte)returnBytes[7] << 8)) / 32768 * 180; // Debug.Log("z-->" + _XuanZhuanJiao); angleX = _FangXiangJiao; angleY = _YangJiao; angleZ = _XuanZhuanJiao; } void OnApplicationQuit() { StartCoroutine(ClosePort()); } IEnumerator ClosePort()//该方法为关闭串口的方法,当程序退出或是离开该页面或是想停止串口时调用。 { isStartThread = false;//停止两个线程的更新 tPortDeal.Abort(); tPort.Abort(); yield return new WaitForSeconds(1);//等一秒钟,让两个线程确实停止之后在执行Close方法 spstart.Close(); yield return new WaitForSeconds(1); } } 以上就是unity串口数据传输(避免假死状况)的个人操作过程啦!
内容来源网络,侵权联系删除
|