2012-01-03 40 views
3

我想在Scala寫一個教程遊戲&正在處理,打算儘可能多地使用FP。但是,我得出的結論是,不可變狀態的遊戲對象在這樣的應用程序中不是有利可圖的。如果一個對象很大,在許多這樣的對象不斷更新的情況下(因此,每個週期都要複製它自己),可能會導致相當密集的內存消耗,例如,使用copy()函數。解決這個問題的默認方法是什麼?我唯一想到的就是將對象切成小塊,以便只有那些需要更新的對象纔會更新,同時讓「大」對象保持不變。Scala遊戲編程 - OOP和FP之間

+1

[scala遊戲編程:在功能風格中推進對象位置]的可能重複(http://stackoverflow.com/questions/4709437/scala-game-programming-advancing-object-position-in-a-functional-風格) – 2012-01-03 15:35:05

+0

耶,謝謝,彼得!我一直在那裏,這是相關的和充分的信息,但不採取相同的方法。 – noncom 2012-01-03 15:49:19

回答

8

遊戲引擎是必不可少的(離散)事件模擬。通常,這些是通過可變數據結構實現的,例如事件堆,可用於空間查詢的quad/oct樹以及大量哈希表。

對於這些數據結構中的每一個,可變變體都更快。此外,不可變的數據結構會產生必須收集的垃圾,因此GC上的壓力會更高,並且您的應用程序最終會變得更慢。在需要實時處理的情況下,GC暫停可能是有害的(例如,它可能會影響遊戲的幀速率),在處理能力較弱的平臺(例如Android)中尤其如此。

至於copy()方法 - 它不必複製整個對象來創建更新的版本。如果您的對象按照樹狀方式(例如,作爲案例類的層次結構)分層組織,那麼更改對象的一個​​屬性需要在此樹中重寫僅一條路徑 - 您不需要重寫所有內容。儘管如此,它的價格會比只有一個可變版本和原地更新更加昂貴。

例子:

case class World(map: Array[Item], players: Vector[Player]) 

case class Player(health: Int, speed: Int, weapon: Weapon, shield: Shield) 

case class Weapon(strength: Int, ammo: Int) 

要更多的彈藥添加到武器,你不必複製整個World

def setAmmo(playerNum: Int, newAmmo: Int, world: World): World = { 
    val p = players(playerNum) 
    world.copy(players = players.updated(playerNum, p.copy(weapon = p.weapon.copy(ammo = newAmmo)))) 
} 

在這個例子中,map,其他players和修改後的Playershield在內存中保持不變,並且不急於複製。

我會建議去一個可變的數據結構來表示狀態 - 除非你有一個併發遊戲引擎(例如)一個模擬遊戲狀態的作者和一系列渲染輸出的讀取器,處理聲音,網絡等等,在這個用例中,不可變數據結構的好處幾乎沒有。

+0

的'副本()'設施看起來像它變成瓦爾斯在瓦爾的更昂貴,有點更安全的變體,因爲它允許改變瓦爾斯像可變值商(VAR)。可以? – noncom 2012-01-03 17:14:18

+0

案例類的'copy()'方法創建一個新的案例類實例,其字段的值等於原始實例中的字段值,除了那些您明確寫入' = ='的字段。不過,這並不做一次深層副本 - 如果某些字段是一個案例類,這種情況下,類實例不是通過'複製拷貝()',只有參考它被複制。 – axel22 2012-01-03 17:31:26

7

首先,不要做過早的優化。你測量過你的代碼嗎?也許有一些具體的瓶頸?由於大多數對象由通過數據結構連接的較小對象組成,因此我認爲您可以使用持久數據結構 來消除此問題。

持久性數據結構是一種數據結構,它總是保持 本身的先前版本時,它被修改;這樣的數據 結構是有效不可變的,因爲他們的行動不 (明顯)更新就地結構,而是始終Daniel Spiewak產生 新更新的結構

Here is wonderful talk對其中的一些。如果你想要更多,請看Chris Okasaki的Purely Functional Data Structures

+1

閱讀Daniel spiewak的演示文稿,它會清除你的'複製'神話。功能性數據結構非常快,問題在於,對於您的用例足夠快嗎? – AndreasScheinert 2012-01-03 16:52:30

+0

@AndreasScheinert謝謝各位,我覺得這些引用非常有趣。我會盡力開發這些信息。 – noncom 2012-01-03 17:06:41

1

只是認爲遊戲狀態本身是可變的。只使用不可變類來處理概念上的值,例如位置,速度等。這可能仍然會產生大量垃圾,但啓用逃逸分析可能會有所幫助。