2016-04-18 403 views
-1

我正在用真正的控件和運行Unity3D的PC構建這款街機遊戲。基本上人們移動一個物理杆並移動一個數字杆。 (這需要儘可能實時)。Arduino到Unity3D延遲/延遲

現在棒旋轉rotary encoder。 帶有中斷的Arduino Mega運行this code會讀取值,然後通過串行將其發送到Unity遊戲。

所有事物都是超級優化的,但是我在移動棒的時刻和顯示在屏幕上的時刻之間有500ms的延遲。

任何想法,以減少這種滯後?我應該使用新的編碼器嗎?一個新的arduino?不同的設置?

非常感謝:)

+0

Wifi還是串口? – Programmer

+0

1/2秒滯後?我懷疑你在Unity方面犯了一些明顯的錯誤。你是否簡單地「模擬」了輸入以檢查你沒有在上游做出一些基本的錯誤? – Fattie

回答

0

沒有統一C#或Arduino的C/C在你的問題提供這樣你只會得到一個建議++代碼。

。使用線程從Unity端的串行讀取。在Unity中嘗試此操作之前,您必須先了解C#Thread,否則您將面臨許多其他問題。

。避免在接收數據時在Arduino或Unity端執行字符串連接(oldString + = newString)。不這樣做會隨着時間的推移而減慢。

。優化您如何從Arduino發送和接收數據。在Arduino一側使用字節數組而不是字符串。

從鏈路張貼在你的問題的Arduino編碼器代碼的例子,它看起來像這樣的事情:

Serial.print("Left = "); 
Serial.print(newLeft); 
Serial.print(", Right = "); 
Serial.print(newRight); 

這不是很好。假設你有編碼器。 Front LeftFront RightBack Left and Back Right編碼器。從每個編碼器獲取這些值。如果值爲正數,則將其縮放至0,127。如果值爲負數,則將其從當前值縮放到-1,-127。使用Map功能可輕鬆完成縮放。

創建一個無符號字符數組或使用字節數組併爲其分配每個縮放值;

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)); 

的陣列發送它們現在,在統一的接收器側,4個字節將在順序到達。閱讀並按發送順序提取值。這節省了Arduino的時間,並提高了接收和發送速度。沒有更多發送長字符串!

。如果全部失敗,請從Arduino Maega更改爲Arduino截止日期。它速度非常快,因爲它使用ARM處理器。請注意,它使用3.3伏而不是伏。所以請確保購買3.3 v編碼器或使用5v3.3降壓。

+0

它確實看起來很奇怪,只有1/2秒的延遲。我懷疑某處有一些嚴重的錯誤。 – Fattie

+0

@JoeBlow即使他說「一切都是超級優化的,我很同意你」。我和Arduino一起工作,.5 lag對於實時性的東西來說是巨大而不利的,我認爲他可能正在做我在#3中提到的,或者編碼器庫製作得不好。如果在我提到的數字#1的Unity方面沒有使用Thread,也會發生滯後。 – Programmer

+0

對,1/2秒似乎是一個很大的滯後...... – Fattie

0

謝謝你的回答!

我做了一些進一步的優化,現在我有大約100ms的延遲。這還是相當多的,並沒有提供很棒的遊戲體驗。

下面是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; 
     } 

...同樣的事情在其他棒。

  1. 你說的是oldRot0 = newRot0; ?我應該避免還是使用它?

  2. 事實上,我正在讀取這個值,使用map函數來縮放然後通過緩衝區輸出它們。我可以做更優化的嗎?

  3. 我正在考慮使用Arduino DUE,但我已經購買並組裝了我所有的編碼器,它們的工作電壓爲5V。我真的不想在3V3上找到新的編碼器,再加上它們看起來不如5V。 我在想的是用更強大的微控制器代替Arduino。 this board會訣竅嗎?它運行在80MHz,與Mega2560的16Mhz相比。