我已将IMU(陀螺仪和Acc&磁力计)连接到我的Unity3D项目并通过USB进行串行通信。
问题是,当我的脚本对游戏代码变得不那么沉重时,串行通信会变慢 - 当IMU的值在某个时间点发生变化时,它们会在几秒后发生变化,随着时间的推移,数据流不能赶上游戏。
我从myPort.ReadLine()
函数调用Update
来从COM端口读取串行数据。
解决方案是什么? - 如果我理解问题,我希望串行数据读取不要等到我的应用程序的下一帧以接收新值。
可能会降低IMU设备的波特率吗?
答案 0 :(得分:3)
您可以采取以下措施来优化项目:
1)您可以更改通信参数。如果您要发送音高,偏航或滚动,请不要将它们作为字符串发送,而是使用IEEE 754格式,将它们作为字节发送。此外,如果您获得四元数值,请不要浪费时间将它们转换为欧拉角。
2)尝试在设置中更改Unity中的更新速率,但要小心更新速率=较慢的统一帧速率。
3)尝试使用高波特率,例如115200
或更高。如果降低波特率,IMU中的数据可能会损坏。
4)在IMU代码中,您可以切换串口通信(您可能不想连续发送所有数据,您可能会偷偷地发送数据)。我的意思是,您可以对数据进行下采样。
5)我不知道您的数据大小,但您可以使用Coroutines&收益或调用。如您所知,Unity不允许我们使用数据接收事件,但您可以创建自己的事件以了解是否已收到所有数据。 (如果您遇到流式传输问题,请尝试discardInBuffer)
6)你可以编写自己的dll(c#dll不会做任何更大的改动,所以使用C ++)。如果您使用的是Windows,则可以使用kernel32.Dll和ws2_32.dll开始搜索。
答案 1 :(得分:0)
所以我认为这个问题的最佳解决方案是线程化。
由于串行数据具有自己的速度,并且不能依赖于游戏更新频率(否则会导致串行流缓冲和大量滞后),以下解决方案对我有用:
在初始化函数(init)中,我调用invokeRepeating - 每0.01秒重复一次的计时器,在那个计时器中,我调用一个线程来读取串行数据。
这是计时器功能的伪代码:
void timerfunction ()
{
if (! threadAlive){
Start new thread - SerialThread ()
threadAlive = true;
}
}
void SerialThread ()
{
Read the Serial Data..
threadAlive = false:
}
这样,当串口内部出现问题时,游戏不会滞后,因为线程会对自身施加压力。
InvokeRepeating将确保在每个固定(理想)的时间内尝试调用线程(读取数据),因此串行数据不会缓冲。
对我来说工作得很好。串行数据速度约为16Hz,游戏帧速率为-10-100 fps。