19173| 5
|
[进阶] Arduino+Unity3D做自己的游戏世界 |
本帖最后由 maker_王 于 2016-12-9 19:47 编辑 看了好长一段时间的U3D,尝试用Arduino和Unity进行通信 http://v.youku.com/v_show/id_XMT ... m=a2hzp.8253869.0.0 虽然能够通信了,不过延时的感觉还是有的 如果时间来得及的话,我还会放一个第三人称的游戏视频 下面是U3D的串口通信脚本,用C#写的,结合了网上还有资料书写的 [mw_shl_code=csharp,true]using UnityEngine; using System.Collections; using System.IO; using System; using System.IO.Ports; using System.Threading; using System.Collections.Generic; public class SerialPortTest : MonoBehaviour { private SerialPort _serialport; private Queue<string> queueDataPool; private Thread tPort; private Thread tPortDeal; private string strOutPool = string.Empty; bool _start; private float Arduino_X; private float Arduino_Y; private float Arduino_Z; public float AX { get { return (Arduino_X-512)>5? Mathf.Clamp01((float)Arduino_X / 512.0f - 1.0f): -Mathf.Clamp01(1.0f - (float)Arduino_X / 512.0f); } } public float AY { get { return (Arduino_Y-512)>5? Mathf.Clamp01((float)Arduino_Y / 512.0f - 1.0f) : -Mathf.Clamp01(1.0f - (float)Arduino_Y / 512.0f); } } public float AZ { get { return Arduino_Z; } } void Start() { queueDataPool = new Queue<string>(); _serialport = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One); try { _serialport.Open(); } catch (Exception _ex) { Debug.Log(_ex); } tPort = new Thread(DealData); tPort.Start(); tPortDeal = new Thread(ReceiveData); tPortDeal.Start(); _start = false; } private void FixedUpdate() { if (Time.frameCount % 120 == 0) System.GC.Collect(); if (!tPort.IsAlive) { tPort = new Thread(DealData); tPort.Start(); } if (!tPortDeal.IsAlive) { tPortDeal = new Thread(ReceiveData); tPortDeal.Start(); } } private void ReceiveData() { try { Byte[] buf = new Byte[1]; string sbReadline2str = string.Empty; if (_serialport.IsOpen) { _serialport.Read(buf, 0, 1); //Debug.Log(System.Text.Encoding.Default.GetString(buf)); } if (buf.Length == 0) return; if (buf != null) { for (int i = 0; i < buf.Length; i++) { string str = System.Text.Encoding.Default.GetString(buf); if (str == "(") _start = true; else sbReadline2str += str; queueDataPool.Enqueue(sbReadline2str); //Debug.Log(sbReadline2str); } } } catch (Exception _ex) { Debug.Log(_ex); } } private void DealData() { while (queueDataPool.Count != 0) { if (_start) { for (int i = 0; i < queueDataPool.Count; i++) { string str = queueDataPool.Dequeue(); if (str == ")") { //Debug.Log(strOutPool); string[] sArray = strOutPool.Split(','); Arduino_X = float .Parse(sArray[0]); Arduino_Y = float.Parse(sArray[1]); Arduino_Z = float.Parse(sArray[2]); Debug.Log("X:" + Arduino_X + "," + "Y:" + Arduino_Y + "," + "Z:" + Arduino_Z); strOutPool = string.Empty; _start = false; } else strOutPool += str; } } } } private void SendSerialPortData(string Data) { if (_serialport.IsOpen) { _serialport.WriteLine(Data); } } private void OnApplicationQuit() { _serialport.Close(); } } [/mw_shl_code] 下面是Arduino的程序: [mw_shl_code=c,true]void setup() { // put your setup code here, to run once: Serial.begin(9600); } void loop() { // put your main code here, to run repeatedly: Serial.print("("); Serial.print(analogRead(A0)); Serial.print(","); Serial.print(analogRead(A1)); Serial.print(","); Serial.print(analogRead(A2)); Serial.println(")"); delay(380); }[/mw_shl_code] Arduino和U3D的串口通信有三种方法实现(都是基于C#中的SerialPort),一个是使用unity自身Updata()(这个方法和Arduino的loop()有点类似),另外一个是用协程Coroutines(这个传输速度稍快),随后一个是使用线程Theard(速度是最快的)。 我上面的脚本中使用的线程,可是需要延时才能接收到正确的数据(这个线程的工作原理还得再看看),不过确实比使用协程方法来的快一些。 最后要说的是这个脚本好像很容易把Unity卡死,第一次运行正常,之后就有可能不能运行了。(有可能是我心太急了还没等Arduino串口通信结束就开始运行游戏) |
© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed