我用真正的控件和运行Unity3D的PC构建这个街机游戏。基本上人们移动物理杆并移动数字杆。 (这需要尽可能实时)。
现在杆转动rotary encoder。 运行带有中断的this code的Arduino Mega读取值,然后通过Serial将其发送到Unity游戏。
所有东西都是超级优化的,但我在移动杆的那一刻和它在屏幕上显示的那一刻之间有500毫秒的滞后。
任何减少这种滞后的想法?我应该使用新的编码器吗?一个新的arduino?一个不同的设置?
非常感谢:)
答案 0 :(得分:0)
您的问题中未提供Unity C#或Arduino C / C ++代码,因此您只能获得建议。
<强> 1 即可。使用Thread从Unity端的串行读取。在Unity中尝试之前,你必须先了解C#Thread,否则你最终会遇到很多其他问题。
<强> 2 即可。在接收数据时,避免在Arduino或Unity端进行字符串连接(oldString + = newString)。不这样做会导致随着时间的推移而减速。
第3 即可。优化您从Arduino发送和接收数据的方式。在Arduino端使用字节数组而不是字符串。
从你问题中链接中发布的Arduino编码器代码示例来看,它看起来像这样:
Serial.print("Left = ");
Serial.print(newLeft);
Serial.print(", Right = ");
Serial.print(newRight);
那不好。我们假设你有 4 编码器。 左前方,右前方,左后方和右后方编码器。从每个编码器获取这些值。如果值正,请将其缩放为0,127。如果值为负数,请将其从当前值缩放到-1,-127。可以使用Map函数轻松完成缩放。
创建一个unsigned char数组或使用字节数组并为其分配每个缩放值;
byte encoders[] = {0, 0, 0, 0}; //4 Encoders
encoders[0] = valueOfScaledFrontLeftEncoder;
encoders[1] = valueOfScaledFrontRightEncoder;
encoders[2] = valueOfScaledBackLeftEncoder;
encoders[3] = valueOfScaledBackRightEncoder;
然后在同一时间发送它们作为字节数组
Serial.write(encoders, sizeof(encoders));
现在,在Unity的接收器端,4个字节将按顺序到达。读取它们并按发送顺序提取值。这节省了Arduino的时间并提高了接收和发送速度。没有更多发送长串!
<强> 4 即可。如果全部失败,请从 Arduino Maega 切换到 Arduino到期。它非常快,因为它使用ARM处理器。请注意,它使用 3.3 伏而不是 5 伏特。因此,请务必购买 3.3 v编码器,或使用 5v 至 3.3 降压。
答案 1 :(得分:0)
感谢您的回答!
我做了一些进一步的优化,现在我有大约100毫秒的延迟。这仍然是相当多的,并没有提供良好的游戏体验。
这是Arduino代码:
#include <Encoder.h>
// Define GPIO of the rotary encoders
Encoder rot0(38,39);
Encoder rot1(40,41);
Encoder pos0(6,7);
Encoder pos1(18,19);
// and so on...
// setting default position
int oldRot0, oldRot1, oldPos0, oldPos1 = -99999;
int newRot0, newRot1, oldPos0, oldPos1;
// and so on...
void setup()
{
Serial.begin(250000);
}
void loop() {
// Reading constantly the encoders
newRot0 = rot0.read();
newRot0 = rot0.read();
newPos0 = pos0.read();
newPos1 = pos1.read();
// and so on...
// Definying a char buffer to output data
char buffer[4];
// IF ROD 1 MOVES : output values
if (newRot0 != oldRot0 || newPos0 != oldPos0)
{
sprintf(buffer,"1%c%c",newRot1,newPos1); // Sending the rod ID and data in char format to save space
Serial.println(buffer);
/* BEFORE: (I changed it to the sprintf buffer)
Serial.print("~1#0#");
Serial.print(newPos1);
Serial.print("#");
Serial.print(newRot1);
Serial.println();
*/
oldRot0 = newRot0;
oldPos0 = newPos0;
}
......其他棒也一样。
你在谈论oldRot0 = newRot0; ?我应该避免使用它还是使用它?
的确,我正在读取值,使用map函数进行缩放,然后通过缓冲区输出它们。我可以做得更优化吗?
我正在考虑使用Arduino DUE,但我已经购买并组装了所有编码器,它们的工作电压为5V。我真的不想在3V3上找到新的编码器,而且它们似乎不如5V。 我想的是用更强大的微控制器取代Arduino。 this board可以解决这个问题吗?与16Mhz的Mega2560相比,它的运行频率为80MHz。
修改强>
毕竟我改变了Arduino Mega的Teensy 3.2,这是非常快的,完全兼容的软件和5V容忍!它大大改善了。我现在不回到8位微控制器......