maker_王 发表于 2016-12-9 19:38:23

Arduino+Unity3D做自己的游戏世界

本帖最后由 maker_王 于 2016-12-9 19:47 编辑

看了好长一段时间的U3D,尝试用Arduino和Unity进行通信
http://v.youku.com/v_show/id_XMT ... m=a2hzp.8253869.0.0
http://v.youku.com/v_show/id_XMTg1NjQzNTUwNA==.html

虽然能够通信了,不过延时的感觉还是有的
如果时间来得及的话,我还会放一个第三人称的游戏视频{:5_159:}

下面是U3D的串口通信脚本,用C#写的,结合了网上还有资料书写的
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;
            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);
                        Arduino_Y = float.Parse(sArray);
                        Arduino_Z = float.Parse(sArray);
                        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();
    }
}


下面是Arduino的程序:
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);
}


Arduino和U3D的串口通信有三种方法实现(都是基于C#中的SerialPort),一个是使用unity自身Updata()(这个方法和Arduino的loop()有点类似),另外一个是用协程Coroutines(这个传输速度稍快),随后一个是使用线程Theard(速度是最快的)。
我上面的脚本中使用的线程,可是需要延时才能接收到正确的数据(这个线程的工作原理还得再看看){:5_177:},不过确实比使用协程方法来的快一些。
最后要说的是这个脚本好像很容易把Unity卡死,第一次运行正常,之后就有可能不能运行了。{:5_182:}(有可能是我心太急了还没等Arduino串口通信结束就开始运行游戏)









dsweiliang 发表于 2016-12-10 13:51:35

感谢楼主的认真分享

iooops 发表于 2016-12-10 22:17:14

哇可以做游戏手柄了

包子11111 发表于 2018-11-15 13:50:33

请问这个程序总是使Unity死机的问题解决了吗

勇往直前 发表于 2020-1-2 14:40:17

大佬,请问有详细教程吗

勇往直前 发表于 2020-1-2 14:40:22

大佬,请问有详细教程吗
页: [1]
查看完整版本: Arduino+Unity3D做自己的游戏世界