Arduino 与 Unity3D TCP通信

 一、通过传输流的方式

#include <WiFi.h>

#define LED_PIN 5
const char * ssid = "Daschow2021";
const char * password = "daschow2021";
void setup() {
  Serial.begin(9600);

  //连接WiFi
  WiFi.begin(ssid,password);

  Serial.print("正在连接Wifi");
  //检测是否连接成功
  while (WiFi.status()!=WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }

  Serial.println("连接成功");
  Serial.print("IP 地址:");
  Serial.println(WiFi.localIP());

  //通过LED 反馈Wifi 连接状态
  pinMode(LED_PIN,OUTPUT);

  digitalWrite(LED_PIN,HIGH);
  delay(100);
  digitalWrite(LED_PIN,LOW);
  delay(100);

  digitalWrite(LED_PIN,HIGH);
  delay(1500);
  digitalWrite(LED_PIN,LOW);
}

void loop()
{

}
using UnityEngine;
using System.Net.Sockets;
using System.IO;
using System.Threading;
using UnityEngine.UI;

public class Test : MonoBehaviour
{
    private TcpClient client;
    private StreamReader reader;
    private StreamWriter writer;
    private Thread clientThread;

    public Button btnA;
    public Button btnB;

    public string serverIPAddress;
    public int serverPort;

    void Start()
    {
        ConnectToServer();

        btnA.onClick.AddListener(() => {
            sendMessage("a");
        });
        btnB.onClick.AddListener(() => {
            sendMessage("b");
        });
    }

    private void Update()
    {
        print(client.Connected);
    }

    void ConnectToServer()
    {
        try
        {
            client = new TcpClient();
            client.Connect(serverIPAddress, serverPort);
            Debug.Log("Connected to Arduino server");

            btnA.interactable = true;
            btnB.interactable = true;

            NetworkStream stream = client.GetStream();
            reader = new StreamReader(stream);
            writer = new StreamWriter(stream);

            clientThread = new Thread(new ThreadStart(ReceiveMessages));
            clientThread.Start();
        }
        catch (System.Exception e)
        {
            Debug.Log("Connection error: " + e.Message);
        }
    }

    /// <summary>
    /// 接收数据
    /// </summary>
    void ReceiveMessages()
    {
        try
        {
            while (client.Connected)
            {
                string message = reader.ReadLine();
                if (message != null)
                {
                    // 处理接收到的消息
                    handleMessage(message);
                }
            }
        }
        //异常断开连接
        catch (System.Exception e)
        {
            Debug.Log("Read/write error: " + e.Message);
        }
    }

    void sendMessage(string message)
    {
        try
        {
            writer.WriteLine(message);
            writer.Flush(); // 清空缓冲区,确保消息被发送
        }
        catch (System.Exception e)
        {
            Debug.Log("Read/write error: " + e.Message);
        }
    }

    void handleMessage(string message)
    {
        Debug.Log("Message received: " + message);
        // 在这里添加逻辑来处理接收到的消息
    }

    void OnDestroy()
    {
        if (client != null)
        {
            clientThread.Abort();
            writer.Close();
            reader.Close();
            client.Close();
        }
    }
}

 二、通过传输流的方式

#include <WiFi.h>

#define LED_PIN 5

const char* ssid = "大西洲01";        // Wi-Fi网络名称
const char* password = "Foresight2022NB";    // Wi-Fi网络密码

WiFiServer server(80);    // 创建一个Wi-Fi服务器对象,监听端口80

const size_t bufferSize = 64;  // 缓冲区大小
char buffer[bufferSize];  // 声明和初始化缓冲区

void handleMessage(const char* message);  // 声明handleMessage函数

void setup() {
  pinMode(LED_PIN, OUTPUT);

  Serial.begin(115200);
  while (!Serial) {}  // 等待串口连接

  // 连接到Wi-Fi网络
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }

  // 打印IP地址
  Serial.println(WiFi.localIP());

  // 开始监听客户端连接
  server.begin();
}

void loop() {
  WiFiClient client = server.available();

  if (client) {
    while (client.connected()) {
      // 检查是否有可用数据
      if (client.available() > 0) {
        // 获取可用数据字节数
        size_t availableBytes = client.available();

        // 限制每次读取的字节数,避免缓冲区溢出
        size_t bytesToRead = min(availableBytes, bufferSize - 1);

        // 读取客户端发送的二进制数据
        size_t len = client.readBytes(buffer, bytesToRead);
        buffer[len] = '\0'; // 在字符串末尾添加终止符

        // 处理接收到的消息
        handleMessage(buffer);

        // 发送响应给客户端
        client.println("Data received");
        client.flush();

        delay(10);
      }
    }

    // 断开客户端连接
    client.stop();
  }
}

void handleMessage(const char* message) {
  // 在这里添加逻辑来处理接收到的字符串数据
  // 根据需要解析和处理收到的数据
  // 以下是一个简单的示例,假设收到的数据指令是控制LED开关

  if (strcmp(message, "a") == 0) {
    digitalWrite(LED_PIN, HIGH);
  } else if (strcmp(message, "b") == 0) {
    digitalWrite(LED_PIN, LOW);
  }
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Http.Headers;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using UnityEngine;

public class NetMgr : MonoBehaviour
{
    private static NetMgr instance;
    public static NetMgr Instance => instance;

    //客户端Socket
    private Socket socket;

    //用于发送消息队列 公共容器 主线程往里面放
    //private Queue<string> sendMsgQueue = new Queue<string>();

    //用于处理分包时,缓存的字节数组和字节数组长度
    private byte[] cacheBytes = new byte[1024 * 1024];
    private int cacheNum = 0;

    //是否连接
    private bool isConnected = false;

    private int SEND_HEART_MSG_TIME = 2;

    private void Awake()
    {
        instance = this;
        DontDestroyOnLoad(gameObject);
    }

    public void Connect(string ip, int port)
    {
        //避免多次连接
        if (isConnected) return;
        if (socket == null)
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        //连接服务端
        IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse(ip), port);

        try
        {
            print("服务器连接成功");
            socket.Connect(ipPoint);
            isConnected = true;

            开启发送线程
            //ThreadPool.QueueUserWorkItem(SendMsg);

        }
        catch (SocketException s)
        {
            if (s.ErrorCode == 10061)
                print("服务器拒绝连接");
            else
                print("连接失败" + s.ErrorCode + s.Message);
        }
    }

    //发送消息
    public void Send(string str) 
    {
        //sendMsgQueue.Enqueue(str);
        socket.Send(Encoding.UTF8.GetBytes(str));
    }

    //private void SendMsg(object state)
    //{
    //    while (isConnected)
    //    {
    //        if (sendMsgQueue.Count > 0)
    //        {
    //            string str = sendMsgQueue.Dequeue();
    //            print("Send:" + str);
    //            socket.Send(Encoding.UTF8.GetBytes(str));
    //        }
    //    }
    //}

    public void Close()
    {
        if (socket != null)
        {
            print("客户端主动断开连接");
            socket.Shutdown(SocketShutdown.Both);
            socket.Disconnect(false);
            socket.Close();
            socket = null;
            isConnected = false;
        }
    }

    private void OnDestroy()
    {
        Close();
    }
}
using UnityEngine;
using System.Net.Sockets;
using System.IO;
using System.Threading;
using UnityEngine.UI;
using Unity.VisualScripting;

public class Test : MonoBehaviour
{
    public Button btnA;
    public Button btnB;
    private void Start()
    {
        if (NetMgr.Instance == null)
        {
            GameObject obj = new GameObject("Net");
            obj.AddComponent<NetMgr>();
        }
        NetMgr.Instance.Connect("192.168.50.49", 80);


        btnA.onClick.AddListener(() => {
            NetMgr.Instance.Send("a");
        });
        btnB.onClick.AddListener(() => {
            NetMgr.Instance.Send("b");
        });
    }

}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ArduinoUnity3D之间的通信可以通过Ardity库实现。Ardity是一个可以在ArduinoUnity3D之间进行简单通信的库。通过在Arduino上安装相关的程序,可以通过串口将数据发送到Unity3D中。在Unity3D中也需要安装Ardity相关的插件,使得Unity3D能够接收Arduino发送的数据。 首先,在Arduino上安装Ardity的库文件,并编写相应的程序,将要发送的数据通过串口发送出去。例如,可以将传感器数据、控制指令等发送到Unity3D中。 然后,在Unity3D中导入Ardity插件,并编写相应的脚本,以接收Arduino发送的数据。在脚本中可以使用Ardity提供的API来读取串口传输的数据,并进行相应的处理。例如,可以将接收到的数据用于实时更新Unity3D场景中的物体状态,或者触发特定的动作。 通过Ardity进行通信的好处是,它简化了ArduinoUnity3D之间的通信过程。使用Ardity库可以方便地在两个平台之间传输数据,使得ArduinoUnity3D能够实现更紧密的交互。同时,Ardity还提供了一些额外的功能,如错误处理和数据校验,可以增强通信的可靠性。 总而言之,通过Ardity可以实现ArduinoUnity3D之间的通信。这种通信方式可以使得ArduinoUnity3D能够更好地协同工作,实现更丰富的交互和实时反馈。使用Ardity库可以简化通信的过程,使得开发人员可以更专注于功能的实现,提高开发效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值