17619浏览
查看: 17619|回复: 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串口通信结束就开始运行游戏)









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

大佬,请问有详细教程吗
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail