unity串口通信

1  偏向硬件方向的详细介绍

http://blog.csdn.net/kasama1953/article/details/51434295

2 偏向软件方向的,使用软件跟硬件交互,显示的屋里数据通过发送串口数据,控制虚拟的运动,自行车项目等等。如何发串口数据,这不是unity关心的,我们只要关心如何接受,并且如何使用它们

首先接受串口数据 using System.IO.Ports; 使用这个命名空间的方法

SerialPort 类

using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Runtime.InteropServices;
using UnityEngine;

public class SerialPortData : MonoBehaviour
{
    public bool Ismulti;
    public int interval_ms = 30;
    public string com = "COM2";
    private List<byte> buffer = new List<byte>();
    public int dataHead = 0xff;
    
    private SerialPort MainPort;
    private bool mainPortIsOpen;
    //public GUIStyle mygui;
  
    private byte[] ReceiveBytes = new byte[5];
    private bool showstr;
    public int speed_locate = 1;
    public int btn_locate = 2;
    public int rotation_locate = 3;
    public float port_speedvalue;
    public int port_rotationvalue;
    public int port_btnvalue;
    private string strport;
    private float t1;

    public static byte speed;
    public static byte doorClose;

    public int port_yugua;

    [DllImport("user32")]
    public static extern int MessageBox(int Hwnd, string text, string Caption, int iType);
    private void OnApplicationQuit()
    {
        this.mainPortIsOpen = false;
        this.MainPort.Close();
    }

    private void OnGU1I()
    {
        //float x = Camera.mainCamera.ViewportToScreenPoint(new Vector3(0f, 0f, 0f)).x;
        //if (this.showstr)
        //{
        //    GUI.Label(new Rect(x, (float)(Screen.height - 50), 700f, 50f), "Port: " + this.com + " Data: " + this.strport, this.mygui);
        //}
        GUIStyle bb = new GUIStyle();
        bb.normal.background = null;    //这是设置背景填充的
        bb.normal.textColor = new Color(1, 0, 0);   //设置字体颜色的
        bb.fontSize = 30;       //当然,这是字体颜色
        GUI.Label(new Rect(30, 20, 800, 400), "data:"+this.strport, bb);
    }

    private void ProcessMsg()
    {
        this.strport = this.ReceiveBytes[0].ToString() + "  " + this.ReceiveBytes[1].ToString() + "  " + this.ReceiveBytes[2].ToString() + "  " + this.ReceiveBytes[3].ToString();
        this.port_speedvalue = this.ReceiveBytes[this.speed_locate]; // 速度
        //Debug.Log("");
        this.port_rotationvalue = this.ReceiveBytes[this.rotation_locate]; // 播放
        this.port_btnvalue = this.ReceiveBytes[this.btn_locate]; //  开关车门
        this.port_yugua = this.ReceiveBytes[4];// 获取第五位
        Debug.Log(this.port_yugua);
        Array.Clear(this.ReceiveBytes, 0, this.ReceiveBytes.Length);
    }

    private void Start()
    {

        
        try
        {
            this.MainPort = new SerialPort(this.com, 0x2580, Parity.None, 8, StopBits.One);
            this.MainPort.Open();
        }
        catch (Exception exception)
        {
            MessageBox(0, exception.Message + "  I'm open" + this.com, null, 0x40);
            this.MainPort = null;
            Application.Quit();
        }
        if ((this.MainPort != null) && this.MainPort.IsOpen)
        {
            this.mainPortIsOpen = true;
        }
        else
        {
            this.mainPortIsOpen = false;

        }
    }
    public void WritePortData(string dataStr)
    {
        if (this.mainPortIsOpen)
        {
            this.MainPort.Write(dataStr);
        }

    }
    private void Update()
    {
        if (this.mainPortIsOpen)
        {
            this.t1 += Time.deltaTime;
            // 30ms 算一次
            if ((this.t1 * 1000f) >= this.interval_ms)
            {
                this.t1 = 0f;
                byte[] buffer1 = new byte[20];
                int length = 0;
                try
                {
                    length = this.MainPort.Read(buffer1, 0, 20); // read  放到buf1中,然后将buf1拷贝到destinationArray中,
                                                        //然后在buf追加destinationArray。当buf长度超过5,解析给ReceiveBytes,清空buf,重新读取
                       Debug.Log("Length  " + buffer1.Length+" "+buffer1[2]);
                }
                catch (Exception)
                {
                    MessageBox(0, "Port breaked! Plaese reconnect!!!  I'm " + this.com, null, 0x40);
                    this.MainPort = null;
                    Application.Quit();
                }
                byte[] destinationArray = new byte[length];
                Array.Copy(buffer1, destinationArray, length);           
                this.buffer.AddRange(destinationArray);
                if (this.buffer.Count >= 5)
                {
                   // Debug.Log("count is out 5");
                    if (this.buffer[0] == this.dataHead)
                    {
                        this.buffer.CopyTo(0, this.ReceiveBytes, 0, 5);
                        this.ProcessMsg();
                        this.buffer.Clear();
                    }
                    this.buffer.Clear();
                }
               // this.MainPort.Write(new byte[] { 0xff, speed, doorClose }, 0, 3);
            }
            if (Input.GetKeyDown(KeyCode.F5))
            {
                this.showstr = !this.showstr;
            }
        }
    }
}
获取数据,然后控制物体运动,一般运动使用第三人称脚本

using UnityEngine;
using System.Collections;
 
/**
 *  @Author : www.xuanyusong.com 
 */
 
[RequireComponent(typeof(CharacterMotor))]
[AddComponentMenu("Character/FPS Input Controller")]
 
public class FPSInputController : MonoBehaviour {
 
private CharacterMotor motor ;
 
// Use this for initialization
void Awake () {
	motor = GetComponent<CharacterMotor>();
}
 
// Update is called once per frame
void Update () {
	// Get the input vector from kayboard or analog stick
	Vector3 directionVector = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
 
	if (directionVector != Vector3.zero) {
		// Get the length of the directon vector and then normalize it
		// Dividing by the length is cheaper than normalizing when we already have the length anyway
		var directionLength = directionVector.magnitude;
		directionVector = directionVector / directionLength;
 
		// Make sure the length is no bigger than 1
		directionLength = Mathf.Min(1, directionLength);
 
		// Make the input vector more sensitive towards the extremes and less sensitive in the middle
		// This makes it easier to control slow speeds when using analog sticks
		directionLength = directionLength * directionLength;
 
		// Multiply the normalized direction vector by the modified length
		directionVector = directionVector * directionLength;
	}
 
	// Apply the direction to the CharacterMotor
	//  此处加入旋转的代码   
	motor.inputMoveDirection = transform.rotation * directionVector;
	motor.inputJump = Input.GetButton("Jump");
}
 
}
如果通过串口数据,加入旋转代码:

  spdata = GameObject.Find("myfirst").GetComponent<SerialPortData>();


float RotationValue = ClampFloat(spdata.port_rotationvalue, vrCenter) * vrDir;


transform.Rotate(new Vector3(0, RotationValue * vrRotateSpeed * 0.01f, 0));               //旋转轴是Y轴(向上)


 motor.inputMoveDirection = transform.rotation * directionVector * vrMoveSpeed * Time.deltaTime * 12;


 float ClampFloat(float value, float center)
    {
        return value - center;
    }

这是一种情况,根据串口旋转,还有就是根据路径点旋转,读取每个路径点,旋转注视

private Transform[] Road_T;            保存所有路径点


  Road_T = GameObject.FindGameObjectWithTag(name).GetComponentsInChildren<Transform>();    获取所有路径点,保存

 private void RotateG() { 
    
        if(Vector3.Distance(this.transfrom.position,Road_T[count].position)<5f){
            canMove = true;
        }
        if (canMove) {

            canMove = false;
            if (count == Road_T.Length - 1) {
                count = Road_T.Length - 1;
                return;
            }
            count++;
        }
        this.transform.rotation = Quaternion.Lerp(this.transform.rotation,Quaternion.LookRotation(Road_T[count].position-this.transform.position),5*Time.deltaTime);
    
    }

是起到平滑过渡的效果  
但你要去控制时间 tim.time 或 time。
datetime  才能看出平滑过渡效果来

LookRotation  旋转插值

此函数作用是生成一个四元数表示的三维朝向,然后可以直接把这个朝向赋给游戏对象来变更其朝向,也可以通过线性插值(Quaternion.Slerp 和 Quaternion.Lerp)来实现游戏对象从当前朝向转到这个新生成的朝向上来

static function LookRotation (forward : Vector3, upwards : Vector3 = Vector3.up) : Quaternion


现在来看 LookRotation 的两个参数,第一个参数 forward,是一个三元组,也就是三个浮点数的组合,这个三元组可以确定世界坐标系下的一个点,从世界坐标系的坐标原点到这个定点就构成了一个三维空间矢量,当我们忽略这个矢量的长度时,它就退化为一个纯粹的方向指示,换句话说,这第一个参数 forward 确定了一个世界坐标系下的方向,而这个方向就是物体转动后 +z 轴所要指向的方向;第二个参数 upwards,也是个三元组(之前没看懂就是没看懂在这个参数上,一致闹不明白这个三元组是干啥用的),这个三元组同样可以确定一个世界坐标系下的方向,物体转动后 x 轴必须与这个方向垂直(如果转动前物体的x轴不满足此条件,那么物体除了改变朝向外还会绕 z 轴旋转以确保转动结束后 x 轴与此方向垂直)。

示例代码:

using UnityEngine;
using System.Collections;

public class LookAtRotation : MonoBehaviour {
    public Transform cube;
    public Transform  target;
    public Vector3 v;
    // Use this for initialization
    public enum Direc {
       UP= 1,
       Forwad=2,

    }
   public Direc direc;
	void Start () {
	
	}
	
	// Update is called once per frame
	void Update () {
        if (direc == Direc.Forwad) v = Vector3.forward;
        else v = Vector3.up;
        cube.rotation = Quaternion.LookRotation(target.position-cube.position,v);
        Debug.DrawLine(Vector3.zero,cube.forward,Color.blue);
        Debug.DrawLine(Vector3.zero,cube.right,Color.red);
        Debug.DrawLine(Vector3.zero,cube.up,Color.green);
	}
}



补充:

运行一段时间发现,串口通信会卡死。。。就是当接受不到数据的时候会卡死! 目测是线程堵死了,看了Read半天也没有发现这个API是否是堵塞,不管了,直接放到子线程处理





over





评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值