本项目为解决Unity与树莓派的远程通信以及低时延视频流传输提供了一种基于UDP协议的解决方案
Read this in other language: English
点击 这里 来预览项目效果
-
Unity端可以向树莓派发送控制信息
-
Unity端可以接收树莓派端发送的实时视频流
最近在做一个远程小车的项目, 控制端采用Unity制作
这个项目可以先为此打下技术基础, 并在此基础上进行后续开发
-
物联网远程控制与实时监测
-
远程视频监控
-
遥操作设备
......
简单来说就是利用UDP协议无连接, 低时延的特点将数据进行传输
然后为了实现远程控制, 需要让Unity和树莓派都作为frp客户端, 同时在阿里云ECS服务器上部署frp服务器端
Unity端发送的UDP数据会先发送给frp服务器, 然后通过服务器再转发给部署有frpc的树莓派端
树莓派端的视频流数据发送给Unity也是同理
- 硬件
- 从学长那白嫖的树莓派4b
- 随便拿的一根网线 (用于连接树莓派和电脑)
- 拼夕夕上买的树莓派摄像头 (应该不是官方的)
- 软件
- Unity版本: 2022.3.62f2c1
- 树莓派系统: Debian GNU/Linux 12 (bookworm)
- 使用的相关Python库: picamera2
- FRP内网穿透小工具: 0.65.0版本
- 其它
- 三个月试用的阿里云ECS服务器
- 聪明的AI助手
- FRP服务器端的配置
-
首先下载FRP, 不过我已经放在Unity工程的文件夹下了
-
配置frps.toml
bindPort = XXXX # 服务器与客户端的通信端口, 默认为7000 auth.token = "secret_token" # 你的神奇小密码, 客户端需要一致 # Dashboard配置 (可选, 如果需要的话) # 日志配置 (可选, 如果需要的话) -
frps, 启动!
注意: 安全组需要开放上述使用的端口(frp 的服务器端与客户端之间的初始连接使用 TCP 协议)
配置frps为系统服务 (开机自启)
-
创建服务文件
nano /etc/systemd/system/frps.service -
添加内容:
[Unit] Description=Frp Server Service After=network.target [Service] Type=simple Restart=on-failure RestartSec=5s ExecStart=/usr/local/frp/frps -c /usr/local/frp/frps.toml LimitNOFILE=1048576 [Install] WantedBy=multi-user.target -
加载并启动服务:
systemctl daemon-reload systemctl enable frps systemctl start frps -
检查状态: 输入
systemctl status frps应显示active (running)
-
- 树莓派FRP客户端的配置
-
依旧要先下载FRP, 注意必须要和服务器端版本相同, 都是0.65.0
-
配置frpc.toml
serverAddr = "你的ECS公网ip" serverPort = XXXX # 和服务器上的bindPort一致 auth.token = "secret_token" # 你的神奇小密码, 和frps.toml上的一致 [[proxies]] name = "随便什么名字都行" # 我取的是test_udp type = "udp" localIP = "127.0.0.1" localPort = XXXXX # 本地端口, 需要跟之后的python代码中监听的端口一致 remotePort = XXXXX # 云端暴露的公网端口(需要ECS安全组开放) -
frpc, 启动!
配置frpc为系统服务 (开机自启)
-
创建服务文件
nano /etc/systemd/system/frpc.service -
添加内容:
[Unit] Description=Frp Client Service After=network.target Wants=network.target [Service] Type=simple Restart=on-failure RestartSec=5s ExecStart=/usr/local/frp/frpc -c /usr/local/frp/frpc.toml [Install] WantedBy=multi-user.target -
加载并启动服务:
systemctl daemon-reload systemctl enable frpc systemctl start frpc -
检查状态: 输入
systemctl status frpc应显示active (running)
-
-
不用那么麻烦的办法
为了让Unity端能够接收到树莓派发送过来的视频流数据, 因此也需要在运行着Unity的设备上部署frp客户端 但是我已经写了一个批处理文件
frpc_setup.bat在windows上部署frpc了, 不过有些地方需要注意:
- 安装frp的版本和安装位置, 安装在Unity可执行文件的同目录下
set "FRP_VERSION=0.65.0" set "FRP_DIR=%~dp0frp_%FRP_VERSION%"
- frpc.toml配置文件信息的写入
echo serverAddr = "你的公网ip" >> "%INI_FILE%" echo serverPort = XXXX >> "%INI_FILE%" # 和服务器上的bindPort一致 echo auth.token = "神奇小密码" >> "%INI_FILE%" echo. >> "%INI_FILE%" echo [[proxies]] >> "%INI_FILE%" echo name = "udp-receive" >> "%INI_FILE%" echo type = "udp" >> "%INI_FILE%" echo localIP = "127.0.0.1" >> "%INI_FILE%" echo localPort = XXXXX >> "%INI_FILE%" # 本地端口, 需要跟之后的C#代码中监听的端口一致 echo remotePort = XXXXX >> "%INI_FILE%" # 云端暴露的公网端口(需要ECS安全组开放)
- 双击
frpc_setup.bat即可在电脑上自动配置frpc了
-
Unity端的C#代码
- 在
UDPCtrl.cs脚本中需要配置frp服务器的IP和本地消息发送的端口// ...existing code... private string serverIP = "服务器公网IP地址"; // 修改为自己的公网IP private int MSG_SEND_PORT = 12300; // unity向frp服务器发送消息端口 private UdpClient udpSendClient; // ...existing code...
- 在
ReceiveCamData.cs脚本中需要配置Unity监听的端口// ...existing code... [Header("视频流接收")] public int MSG_RECEIVE_PORT; // Unity监听frp服务器端口, 和本机frpc.toml中的localPort一致 public RawImage display; private Texture2D texture; // ...existing code...
- 在
-
树莓派端的Python代码
- 在
Pi.py中需要配置树莓派端的监听端口, 我这里默认12345# ...existing code... # UDP 指令接收端配置 UDP_CTRL_IP = "0.0.0.0" UDP_CTRL_PORT = 12345 # 树莓派端监听frp服务器端口, 和树莓派frpc.toml中的localPort一致 # ...existing code...
- 在
Pi.py中配置frp服务器的IP和本地消息发送的端口# ...existing code... SERVER_IP = "服务器公网IP" UDP_VIDEO_PORT = 13300 # 树莓派端向frp服务器发送消息的端口, 和Unity端frpc.toml中的remotePort一致 # ...existing code...
- 在
- 树莓派端发送视频流
-
对视频帧进行JPEG编码, 降低传输数据量
-
将一帧视频数据分成多个视频帧分片, 每个视频帧分片又包括帧分片标识和帧分片数据
-
将一整个帧数据分成小的帧分片, 每个分片1024字节, 同时每个帧分片带有一个头部标识
- 帧ID: 同一帧的所有包, ID都一样
- 帧总分片数: 这一帧一共切成多少分片
- 当前分片序号: 这是第几个分片
- Unity端接收视频流
-
在
ReceiveUDPdata子线程中先将接收到的数据放入dataQueue中, 等待主线程处理 -
主线程处理
dataQueue中的数据, 分为以下步骤-
解析帧分片数据(帧ID,帧总分片数和分片ID)
-
提取分片数据
-
删去超时帧数据
-
处理分片数据
-
接收完一帧数据, 进行合并和解码
-
-
更高的帧率 目前视频流的传输能够稳定在30帧(ECS服务器带宽10Mbps)
-
更低的时延 在校园网情况下, 当前的传输时延大约在80ms到150ms之间. 这基本能满足远程小车的实时控制, 但是对于更高要求的使用场景来说需要进一步优化



