2012-03-07 35 views
2

直到最近,我們的遊戲通過從場景的背景紋理的一部分獲取顏色數據來檢查碰撞。這很好,但隨着設計的改變,我們需要檢查多個紋理,並決定將這些全部渲染到一個RenderTarget2D並檢查碰撞。是否有一種廉價的方法在每幀的基礎上從RenderTarget2D傳輸顏色數據?

public bool TouchingBlackPixel(GameObject p) 
    { 
     /* 
     Calculate rectangle under the player... 
     SourceX,SourceY: Position of top left corner of rectangle 
     SizeX,SizeY: Aproximated (cast to int from float) size of box 
     */ 

     Rectangle sourceRectangle = new Rectangle(sourceX, sourceY, 
                (int)sizeX, (int)sizeY); 

     Color[] retrievedColor = new Color[(int)(sizeX * sizeY)]; 

     p.tileCurrentlyOn.collisionLayer.GetData(0, sourceRectangle, retrievedColor, 
                0, retrievedColor.Count()); 

     /* 
     Check collisions 
     */ 
    } 

我們一直存在的問題是,自從轉移到渲染目標以來,我們正在經歷FPS的大幅減少。

從我們所讀到的看來,問題在於,爲了從RenderTarget2D獲取數據,您需要將數據從GPU傳輸到CPU,並且速度很慢。由於我們需要兩次運行相同的功能(每個玩家一次)並且不能保持相同的數據(它們可能不在同一個區塊中),這使我們變得更加複雜。

我們已經嘗試將GetData調用移動到tile的Draw函數並將數據存儲在成員數組中,但這似乎沒有解決問題(因爲我們仍然非常有規律地調用GetData - 向下從每次更新兩次到每次抽獎一次)。

任何你可以給我們提供的幫助都會很大,因爲這個碰撞系統給我們帶來的力量是相當不可思議的,但是渲染目標的開銷會導致它無法保持。

+0

你生成一個着色器碰撞層?通常情況下,您會在CPU上保留一個本地副本,並使用該數據結構或衍生數據結構進行碰撞檢測,或處理着色器內的碰撞。 – 2012-03-07 16:17:02

+0

通過在圖形設備上設置渲染目標,然後繪製一個精靈批次來創建碰撞圖層。我不認爲這使用着色器。 – LlamaCloud 2012-03-07 16:55:50

回答

1

簡單的答案是:不要那樣做

這聽起來像是將你的碰撞數據合成分流到GPU是一種性能優化,它不起作用 - 所以正確的做法是恢復變化。

你應該簡單地在CPU上進行碰撞檢查。而且我還會建議,多次運行碰撞算法並通過組合結果來確定碰撞響應可能會更快,而不是將整個場景合成到單個圖層並運行一次碰撞檢測。

如果您在執行碰撞前使用渲染目標來支持轉換,則尤其如此。

(對於簡單的2D像素碰撞檢測,看this sample。如果你需要轉換的支持,看到this sample爲好。)

+0

將它移動到GPU並不完全是我們的選擇,因爲我們希望一次檢查所有圖層並在GPU上呈現目標,但我明白您的目標。這是否意味着如果沒有不利的幀率,就無法使用我們現有的系統?將碰撞檢測本身卸載到GPU以避免必須隨機擺放數據是否是一個好主意?我之前看過這些例子,而且我們的系統實際上比它們好一些,但是當您使用渲染目標(因爲它們需要從GPU轉移到CPU)時會下降。 – LlamaCloud 2012-03-08 08:15:50

+0

我不能肯定地說,在某些幀率/硬件預算中沒有*方法來獲得它(特別是因爲我沒有細節)。但我可以向你保證,這是一個非常非常緩慢的操作。在CPU上使用編程和硬件資源會更好。如果在任何時候必須將數據傳回CPU,將整件事物卸載到GPU可能是一個糟糕的計劃。 – 2012-03-08 09:21:59

+0

我認爲你可能是對的。我們只需要分別檢查每個對象上的衝突,而不是統一系統。這是一個遺憾,因爲我們有一個很好的系統,可以從衝突中得到一些令人印象深刻的反饋,但是每幀訪問GPU的開銷太高。 – LlamaCloud 2012-03-08 12:19:26

0

我想,你的瓷磚的碰撞層不會改變。或者至少變化不是很頻繁。因此,您可以將每個圖塊的顏色存儲在數組或其他結構中。這會減少從GPU傳輸到CPU的數據量,但要求存儲在RAM中的附加數據不會太大。

+0

這會很好,但是我們不能排除碰撞層會改變的可能性。我們現在有一塊磚塊,它具有不斷變化的層次,並且所有這些磚塊都可以由玩家賦予它們變化。這確保了使用這種方法的可能性,因爲只要玩家進入移動瓷磚(或者自己改變瓷磚),我們將不得不獲得新的數據,並且這會立即殺死幀速率。 – LlamaCloud 2012-03-07 16:07:58

+0

另一種選擇是實現一種緩存系統,只有在已更新並且必要時才輪詢GPU中的信息。 – 2012-03-07 21:34:47

+0

正如在問題文字中提到的(儘管我已經注意到,稍微不準確,我會編輯更正),但我們試圖在獲取數據時抓取這些數據,但這並沒有產生顯着的改進。我們還沒有嘗試確保它只在變化時才抓住它,但即使它改變了每一幀(就像我們在'雨'場景中那樣),我們也必須能夠使用這個系統,所以這不能解決問題。 – LlamaCloud 2012-03-07 21:50:21

相關問題