2016-08-19 103 views
0

我在Unity中有腳本,與另一個Python應用程序交換數據。它有一個while循環來偵聽UDP消息作爲後臺線程。此外,該腳本通過更新功能每幀請求新數據。Unity - 如何減少在更新和GC中花費的時間

當我收到一條消息後,腳本將其解析爲一個字符串,並且需要通過製表符來分割字符串以檢索所有值。目前,該字符串包含Unity作爲玩家輸入所需的眼球跟蹤器和遊戲杆數據。

UDPController.cs

private void init() 
{ 

    // define address to send data to 
    pythonEndPoint = new IPEndPoint(IPAddress.Parse(IP), pythonPort); 
    unityEndPoint = new IPEndPoint (IPAddress.Parse (IP), unityPort); 
    pythonSock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); 


    //define client to receive data at 
    client = new UdpClient(unityPort); 
    client.Client.ReceiveTimeout = 1; 
    client.Client.SendTimeout = 1; 

    // start background thread to receive information 
    receiveThread = new Thread(new ThreadStart(ReceiveData)); 
    receiveThread.IsBackground = true; 
    receiveThread.Start(); 

} 

void Update(){ 
    if (Calibration.calibrationFinished && startRequestNewFrame) { 
     RequestData(); 
    } 
} 
private void RequestData() { 
    // Sends this to the UDP server written in Python 
    SendString("NEWFRAME"); 
} 

// receive thread which listens for messages from Python UDP Server 
private void ReceiveData() 
{ 

    while (true) 
    { 

     try 
     { 

      if(client.Available > 0) { 

       double unixRecvTimeStamp = DataManager.ConvertToUnixTimestamp(DateTime.Now); 
       byte[] data = client.Receive(ref pythonEndPoint); 

       string rawtext = Encoding.UTF8.GetString(data); 

       string[] msgs = rawtext.Split('\t'); 

       string msgType = msgs[0]; 
       double pythonSentTimeStamp = double.Parse(msgs[msgs.Length-1].Split(' ')[1]); 

       DataManager.UdpRecvBuffer += '"' + rawtext + '"' + "\t" + pythonSentTimeStamp + "\t" + unixRecvTimeStamp + "\t" + DataManager.ConvertToUnixTimestamp(DateTime.Now) + "\n"; 

       if (String.Equals(msgType, "FRAMEDATA")) 
       { 

        DataManager.gazeAdcsPos = new Vector2(float.Parse(msgs[1].Split(' ')[1]), float.Parse(msgs[2].Split(' ')[1])); 
        float GazeTimeStamp = float.Parse(msgs[3].Split(' ')[1]); 
        DataManager.rawJoy = new Vector2(float.Parse(msgs[4].Split(' ')[1]), 255 - float.Parse(msgs[5].Split(' ')[1])); 
        float joyC = float.Parse(msgs[6].Split(' ')[1]); 
        float ArduinoTimeStamp = float.Parse(msgs[7].Split(' ')[1]); 
       } 

      } 

     } 
     catch (Exception err) 
     { 
      print(err.ToString()); 
     } 
    } 
} 

所以根據統一探查,好像有一個巨大的行爲更新所花費的時間量,尤其是裏面UDPController.Update()和GC.Collect的。我最初的假設是,也許我創造了太多的字符串和數組超時,垃圾收集器經常踢,以刪除未使用的內存空間。

Unity Profiler - Showing high CPU Usage and Time in Behaviour Update

所以我的問題是,是我的假設嗎?如果是這樣,我如何重寫這段代碼來提高我的表現,並減少FPS和感知滯後的下降。如果不是,問題在哪裏,因爲目前遊戲開始滯後10分鐘左右。

此外,有沒有更好的數據傳輸方式或格式?看起來我可以使用JSON,Google Protocol Buffer或msgpack之類的對象,或者這會是一種矯枉過正的行爲?

+0

如果你會跳過一些更新?你需要每幀還是每秒兩次就足夠了? – Everts

+0

@Everts是的,我需要它的每一幀。基本上數據包含打開門和移動玩家的眼睛座標和操縱桿位置。 –

回答

0
  1. 我可以在while循環中看到很多局部變量(以及數組)。本地變量導致垃圾收集器運行。您應該聲明方法之外的所有變量。

  2. 此外,請避免while/update()中的字符串操作爲strings are immutable。因此,您的代碼將創建一個新副本以在每個並置後存儲結果。在這些情況下使用StringBuilder以避免GC。

Read More

相關問題