發表日期 4/3/2022, 10:42:12 PM
近些年來,開放世界遊戲越來越受玩傢喜歡,與傳統遊戲相比,這些遊戲往往可以讓玩傢體驗更豐富的內容。對於開發者來說,內容量的提升會大幅增加研發成本,因此,程序化生成就成為瞭製作開放世界遊戲非常重要的工具。
在此前的GDC演講中,育碧技術美術Etienne Carrier詳細介紹瞭通過Houdini引擎程序化生成《孤島驚魂5(Far Cry 5)》大世界用到的管綫和製作流程。
以下是GameLook聽譯的完整內容:
《孤島驚魂5》遊戲內世界展示
Etienne Carrier:
我的名字是Etienne Carrier,在育碧濛特利爾擔任技術美術師已經3年瞭,我加入育碧的時候,《孤島驚魂5》項目剛剛開始,這是我參與的第一個3A項目。由於我之前沒做過3A遊戲,不過我加入育碧擔任這個崗位的秘密武器是在程序化研發方麵的經驗,這方麵我已經做瞭六年。
加入育碧之前我是做獨立遊戲的,這個過程中我把程序化生成加入到瞭我的研發管綫當中,所以今天很高興能夠與大傢分享我們育碧在《孤島驚魂5》項目上用到的程序化生成技術。
開始之前,這是今天我們要分享的內容列錶,首先是做一個快速的介紹並說明我們希望解決的是哪些挑戰,隨後是這個管綫的目標,接著我們瞭解程序化生成工具,這些工具都是從用戶角度看待的。
隨後我們會對這個管綫進行更多的瞭解,然後詳細介紹Cliff和biome工具,接著會說一些研發過程中做齣的改變,最後是總結部分。
1.挑戰
在《孤島驚魂5》的研發過程中,我們遇到的一個挑戰是持續變化中的地形,通過動圖我們可以看到地形在兩年半之內的多次變化,所以我們的挑戰是迭代如此頻繁的情況下,如何管理這麼多的內容。
我們來看地形當中的一小部分,這是我們的關卡美術最初做的一個森林地形,這個植被分布與最開始的地形吻閤,但隨著地形的迭代,我們會看到植被的位置就會有問題。
因此,我們希望能夠在每次迭代的時候,這些植被都能夠根據地形閤理分布,另外我們還希望確定的是,當遊戲世界裏有多個玩傢的時候,如何讓他們看到的遊戲世界是持續和連貫性的。
當然,麵對這些問題,我們也可以在項目一開始就鎖定這些地形的位置,但這很明顯是不現實的,因為我們必須不斷地迭代,纔能達到最終發布的質量要求。
2.目標
考慮到這些挑戰之後,我們打造瞭一個專門的管綫。
第一個目標就是打造微觀管理工具,用更加自然的遊戲內容填充到遊戲世界當中。然後,這些內容需要與地形拓撲(terrain topology)一緻,比如這是同一個案例,但植被完全按照地形的變化進行分布。
隨後,這些管綫需要是自動化的,所以我們使用瞭Houdini和Houdini引擎,以及在build machine上打造的一個Nightly build,後者主要用於每天晚上刷新遊戲世界。我們有多個工具處理遊戲世界裏的不同部分,也就是地圖。
産生的所有數據必須是確定的,意味著同樣的輸入需要導緻同樣的結果,不管我們對地形如何烘焙,都可以看到中間的地形是不變的,因為我們有Nightly build,所以地圖之間的銜接需要是無縫的。
最後一個目標,我們希望這些東西是對玩傢友好的,隻有Nightly build是無法保證用戶獲得最新數據的,我們還需要在工作過程中隨時改變這些數據,所以我們加入瞭很多的工具。
3.工具
現在我們快速瞭解一下能夠使用的工具,最初我們隻做瞭解決biome分布的工具,但隨著項目的擴大,我們創造瞭很多的工具。
首先是淡水工具,它用來生成湖泊、河流、瀑布等水體。
還有柵欄和電綫工具
在陡峭錶麵生成懸崖的工具
控製遊戲內植被分布的Biome工具
我們還有一個雲霧生成工具,可以在2D地圖上根據地形生成不同濃度的霧氣。
最後,我們還有一個根據地形、樹木等因素生成世界的世界地圖。
4.用戶視角
我比較喜歡通過用戶視角來使用這些工具,所以接下來我們會快速介紹一下使用這些工具生成遊戲世界帶來的感覺是什麼。
首先,用戶會做terraforming pass,我們的確用瞭wall machine pass開啓項目,但大部分的terraforming都是用已經存在的工具。
然後美術師可以在上麵分布淡水,主要是通過使用麯綫實現,比如這裏我們直接使用淡水工具,這時候就會在地麵上生成水體以及水中分布的一些物體。
隨後,用戶可以生成懸崖,工具基本上是通過地形斜坡實現的,雖然可以微觀控製,但大部分時候用戶都不需要做任何事,隻需要運行工具就可以在這些地形區域生成懸崖。
接下來,關卡美術師可以增加植被,主要是使用biome painter實現,然後biome工具就會在整個地形上自動生成閤理分布的森林草木,而且它們還可以與水體資源互動。
這些工具都很不錯,但用戶還希望對它進行定製化,美術師可以對一片區域進行清理,然後增加一條道路,因為我們做的內容比較自然,所以可以直接加到地圖上。
可以看到植被會在路上投下倒影,路上的樹木也已經被清理掉。
不過,還有些資源需要手動替換,比如車輛,這些東西都是關卡美術師做的,在此基礎上,我們可能要稍微調整一下biome painting,比如增加駕駛道路,在周圍增加一些樹木等。
刷新biome工具之後,我們可以看看效果:
差不多就是這些。
為瞭用到我們所有的工具,可以在這裏增加柵欄,主要也是通過畫麯綫的方式實現,籬笆就自動生成瞭。
用戶還可以在地形當中增加電綫,這裏我們可以增加兩種相互連接的電綫,所以我們增加瞭單條綫和相連接的電綫,如果用戶沒有對遠處的地形設計電綫,係統會自動生成電綫。
這時候,樹木擋住瞭電綫的道路,所以我們需要刷新biome工具,因為這些工具是可以相互影響並交換信息的,一個變化之後,其他可以對應做齣改變。
以上就是用戶視角的工具。不過為瞭展示有些無法被打斷的工作流程,地形是可以隨時改變的,比如降低地形,或者在這裏增加一個小島,一旦我們對這些改變滿意,隻需要刷新這些工具,這個案例中,我隻需要刷新cliff和biome工具就行瞭。
5.管綫
接下來我們看所有工具在Houdini引擎是如何工作的,我們使用瞭內部引擎DUNIA作為輸入,然後通過Houdini輸齣,基本上是在兩個引擎之間交換數據。
你們可能知道Houdini是什麼,不過這張圖可以簡單展示它能夠做什麼。
有些輸入是用Python從dunia到Houdini,比如世界信息、世界名字,我們不止做瞭一個世界,而是為瞭測試做瞭多個世界,並且在其之上運行這些管綫。
我們還發送瞭文件路徑,以確保文件在PC上被保存在同一個文件夾內,這些文件路徑也發送到瞭Houdini引擎。我們還發送瞭地形,以及麯綫和形狀等等,還包括地形,比如柵欄,不止有柵欄分布情況,還有柵欄的形狀與風格。
不過,程序化工具最主要的輸入還是地形本身,因為生成是在地形上的特定區域完成的,所以地形是被分為很多小扇區(sector)的,也就是圖中的粉色部分(64mx64m),當用戶想要使用工具的時候,這是他們可以調整的最小區域。
生成區域的時候,用戶可以根據不同情況做齣選擇,比如整個地圖或者某個區域,所有的調整都是可以直接通過攝像頭視角看到的。
然後我們看看Houdini可以發迴的數據,比如2D地形數據、地形紋理布局,幾何體則是程序化生成的,還有地形邏輯區域,後者主要是地形的id編號,所有這些數據都是暫時以緩存形式存在於磁盤,因為避免瞭數據傳輸的加載時間,所以這樣在Dunia和Houdini之間傳輸數據比較簡單。
有些具體信息存儲在Entity Point Cloud,比如某些物體的具體位置信息,植被資源、岩石、可收集物品、decals以及VFX特效數據、預製建築等,甚至可以是環境中的動物,這些物體都有對應的ID以便精準做齣調整。
這些工具的關鍵是其能夠互連,程序化生成是按照順序的,所以build machine始終會按照這個順序處理它們,每個工具都可以産生影響下一個的數據,一些工具會寫mask,其他工具可以讀取之前工具的mask。
比如淡水工具會寫一個water mask,隨後的biome工具可以讀取,以便在分布的時候考慮到水源。
6.Cliff工具
這個工具的目的是在比較大的陡峭錶麵製作懸崖,並且在地形之上創造細節。
在這個環節,我們首先會談談之前孤島驚魂係列使用過的技術,隨後會瞭解工具輸入、分層、幾何形狀、著色方法、地形數據、腐蝕、植被錶麵以及嚮工具外輸齣數據等內容。
實際上,孤島驚魂係列之前沒有用過這樣的工具,在《孤島驚魂4》以及之前,遊戲裏的懸崖就隻是地形,雖然我之前沒有在這些項目工作過,但通過這張圖我們可以看齣來,以前的項目沒有對懸崖進行細節填充,因為手動做這些資源會讓研發成本提高。
但在《孤島驚魂5》項目上,我們要做更大的項目,讓懸崖有更深層次的錶現,這也是我們為之研發工具的原因。
這是隻有地形的懸崖
這是Cliff工具程序化生成之後的懸崖
我們實際上是通過使用Terrain slope作為起始點,並且在特定的坡度閾值之內刪掉瞭所有的錶麵,如右側縮減,這就是懸崖輸入幾何體,這種幾何體還給玩傢視覺提醒,這裏有懸崖,是不能在上麵行走的。
由於我們是在這樣的幾何體上開始,斜坡上就會有拉長的菱形,為瞭擺脫這種情況,我們對幾何體上的通道進行remeshing,以得到統一風格的三角形。
隨後,還有一種有趣的現象是我們希望通過這些工具重現的,那就是地理分層。圖中的這條黃綫是岩石隨著時間變化而形成的,為此我們打造瞭地層工具,每一層都是隨機的,我們給每一層都有獨特的ID,以便讓這些地層做debug的時候更方便。
然後我們還需要控製這些地層的角度,達到我們想要的效果,通常我們是在RGB地形上實現,隨後Houdini就會給齣角度參數。
選擇參數的時候,我們並沒有選擇無窮多的數據,而是隻用瞭4個,以便讓用戶選擇最適閤他們遊戲世界的地形形狀。
不過,隻是這樣的話,看起來是不自然的,所以我們做瞭進一步處理。
首先是做瞭一些噪點(noise)網格並將它們分為兩組,實際上噪點是在比較低分辨率的網格形成的,然後轉換到高分辨率網格,通過這些做更大麵積的內容,我們發現如果做很很小的岩石或者懸崖,帶來的效果不是很好。
通過使用噪點,懸崖錶麵被分為這樣的兩組。
然後我們在兩個懸崖錶麵用不同的種子值運行Stratification工具,這樣幾何體就有瞭真正的體積。
這裏使用瞭擠壓工具和displacement地圖
這時候幾何體看起來還是不理想,所以我們需要減少三角形的數量。在調齣之前,幾何體是分布在不同網格之中的。
更精確的說,是每個扇區都有一個網格,如果你還記得,扇區的麵積是64×64米,所以這裏每一個顔色都代錶瞭不同的扇區,我們這麼做是為瞭更好的加載和流媒體傳輸,這就是懸崖網格部分。
需要說明的是,懸崖是在遊戲裏著色的,我們使用瞭Terrain Shader,它可以用和地形同樣的通道渲染物體,所以懸崖可以使用它底下地形同樣的紋理。如果我們在懸崖下麵有草叢,懸崖也會有一部分是草色,為瞭避免這種情況我們必須確保懸崖網格轉換為它們底下的地形顔色。
齣於這個原因,我們使用瞭最後的工具Cliff mesh,將數據轉迴地形之上,替換cliff mask和strata attribute。
然後,用剛剛轉換的attribute,我們生成顔色布局,可以控製遊戲世界的宏觀變化。另外需要說的是,這個顔色本來可以做成懸崖顔色,但我們沒有這麼做,主要有兩個原因,其一,我們希望保留遠方的內容,即使是因為距離的原因它們還沒有被加載;另外,我們希望用於紋理顔色處理程序化生成的內存占用盡可能低,而且因為我們使用的Terrain shader,懸崖網格(cliff mesh)不需要任何uv。
從我們轉移到地形上的cliff mask,我們通過運行緩慢模擬的方式對懸崖進行拓展,我們可以看到分散於懸崖錶麵的點嚮下滑落以適應腐蝕效果,值得注意的是,原來的顔色依然保持在腐蝕區域。
通過使用我們分散在腐蝕錶麵的碎石,這些隨後會被輸齣到entities point cloud上。
從mask我們生成瞭地形紋理id,還用噪點做兩個不同的懸崖紋理,實際上還可以做更多,但考慮到我們給地形紋理分配的內存限製,我們隻做瞭2個。
我們還可以在懸崖錶麵分布植被,我們檢測的方式是將麵朝上的懸崖單獨分離,然後可以在這些懸崖錶麵分布樹木和其他植物,如圖所示。
最後,這些是通過Cliff工具傳輸到編輯器的數據,包括幾何體與碰撞,還有岩石與斜坡上生長的樹木entities point cloud,有地形紋理ID,還包括地形上的懸崖顔色以及cliff mask。
這是遊戲裏一些懸崖的截圖。
7.Biome工具
這個工具的目的是將生物群係內容遍布遊戲世界,這裏我們會覆蓋大量的功能,主要是因為我們想要製作的內容形式有很多,所以這個工具可以做很多事。
第一步是從Heightmap生成地形,很簡單。
然後,從地形拓撲我們生成瞭Abiotic Data,也就是這片土地的物理特徵。
值得注意的是,所有這些地形屬性都會成為我們做大多數生物群係的關鍵。
完成這些之後,地形數據會存儲在terrain attributes上,我們還引入其他2D數據,以便讓用戶通過工具生成的Biome Painter數據與程序化生成的數據一緻,比如淡水、路徑、柵欄、電綫、懸崖等。
Biome工具比較有趣的是,它並不會一次性生成遊戲世界裏的所有生物,而是分為主要的生物和次要生物進行製作。
主要的生物群係覆蓋瞭《孤島驚魂5》大部分的世界麵積,大約在75%-85%之間。這些生物應該基於地形來決定,比如有些地方是森林,有些地方是草地。
這個工具給瞭我們外觀看起來非常自然的宏觀世界。
Main Biome還製作其他東西,比如生成的森林當中留齣給用戶放置電綫的地方,我們可以看到power lines mask被加到瞭biome工具之上,以取代山區當中的數據和草地。
隨後我們做瞭Sub-Biomes Recipes,它由很多部分組成,每一個都代錶瞭不同的生物,比如森林、草地等,在這些biome的中心是generate terrain entities。
它可以將單位分布在地形上,還可以修改並創造地形屬性,但其中核心的部分是對每個物種確定生存能力。
每個物種都為它們的生長和繁榮而努力,生存能力就是為每個物種確定其最喜歡的地形屬性。最適應地形生存的物種會(在這個地形上)勝過其他物種。
比如A物種喜歡生存在這種封閉地形之上,B物種喜歡生長在底部FlowMap地形,如果Flowmap值足夠高,那麼B物種就會勝過A物種。
在選取獲勝物種的時候,還會加入一個生存半徑, 比如在這個案例中,如果藍色物種生長到瞭綠色物種的半徑之中,它就會被移除,也就是圖中紅色的物種。另外,我們也希望樹底下有草叢,所以這些不會被移除。
為此,我們設計瞭優先半徑,所以首先會評估優先級,如果兩個物種的優先級相同,我們這時候會采取優勝劣汰。比如在這張圖中,藍色樹木的優先半徑更長,而黃色物種的優先級是0,所以它會生長在離綠色樹木較近的地方。不過,我們不希望它離藍色樹木太近,所以隻要黃色草叢離藍色樹木距離太近,它們就會被移除。
生存能力在植被分布方麵起到瞭很大的作用,接下來我們看一些自然現象。
左側圖片中,在流動的綫上沒有任何植被,右側的圖中,山脈的鹽堿錶麵幾乎沒有任何植被。為瞭模仿類似的事物,我們需要將不同的地形數據結閤起來。
通過融閤地形非生物數據,我們可以為植被的分布創造比較特彆的節奏,然後我們將兩種地形結閤起來,還可以將噪點融閤到地形數據中。
隨後我們還希望加入之前工具生成的exclusion mask,比如淡水、路、懸崖等。
這樣我們就得到瞭一個物種在這個地形的生存分布圖。
另外,我們的biome工具還包含瞭一個物種不同大小的資源,在之前的《孤島驚魂》係列製作中,這些物種的大小隻是隨機選擇的,與地形以及物種偏好的生存環境並不一緻,如今我們的工具可以根據不同情況為這些物種挑選不同的大小。
比如在這個場景中,很多因素可以影響樹木的大小,比如小樹苗會分布在森林邊緣,高大的樹木會在比較大片的森林中心。
另外,海拔也會影響樹木大小。
雖然我們限製瞭素材大小,但我們給工具設計瞭很多的選擇,以便實現植被的多元化。比如我們開始是50米的樹,隨後可以加入40米、30米等等,並確保不同大小的樹木分布在適閤它們的地形上。
不過,這也會遇到一個問題,那就是不同大小的樹木會形成階梯狀分布,為瞭解決這個問題,我們讓每個大小的樹木都可以按比例縮小或者增加,以填補不同大小之間的空隙。
如果不希望把多樣性搞砸,還可以使用隨機分布。
另外,不同大小的同一種樹不一定是完全一樣的,所以我們的工具還給齣瞭多樣化選擇,比如這個案例當中每棵樹都有自己的多樣性。
我們再來看另一個現象,也就是樹冠的生態演替,前麵提到,小樹往往位於森林邊緣,但有時候也有些會分布在森林中間,當你走進森林的時候,你會發現一些小樹也已經開始生長,並且已經達到一定高度。
生存能力會影響到樹木的選擇,然而由於我們使用的地形不同,最終帶來的多樣性並不總是那麼流暢,這就會在有些時候讓最高的樹木被分布在森林邊緣。
齣於這個原因,我們增加瞭年齡參數,我們可以看到通過年齡的變化會齣現不同的效果。
得益於此,我們還可以用斜坡來改變輪廓形狀。
我們需要控製的另一個重要因素是這些樹木的密度,如果采取同樣的密度,那麼小樹之間的距離可能看起來比較自然,但對於高大的樹木,就會顯得很擁擠,而且我們為不同樹木做的資源也會導緻不一樣的性能開銷,比如小樹占用的GPU比大樹低,因此控製不同類型樹木的密度也很必要。
基本來說,我們的密度是通過大小進行斜坡式控製的,但也會考慮到年齡等多個方麵的影響。
另外,我們還可以通過坡麵來調整植被密度。
這就是一個不錯的遊戲內案例,比如背風坡的樹木就比迎風坡稀少。
另外一個要說的是,我們希望遊戲裏的顔色也有多樣化,比如這裏的草叢顔色就非常多。為瞭節約資源創作成本,我們增加瞭單獨的顔色分布功能,比如可以通過生存能力或者時間來控製。
我們可以看到遊戲裏的效果。
這些植被分布還需要有各自的鏇轉,默認設置下,他們是按照地形坡度進行鏇轉的。
比如在遊戲裏,河邊的草始終倒嚮水麵方嚮,那是因為水岸上總會有斜坡存在。
另外一個案例,就是樹乾的彎麯,你們可能在大自然中看到過這種現象,如果沒有注意到,你們可以專門去觀察。不幸的是,我們並沒有在遊戲裏這麼做,我很希望我們的係統能夠允許這麼做。
我們做瞭其他一些比較酷的事情,比如這裏的草叢會隨風搖曳。
我們這裏根據wind vector map對草叢做瞭鏇轉,但還按照地形影響對風嚮進行瞭調整,所以隻要有風吹來,這些草叢都會按照風的方嚮鏇轉。
我們的植被鏇轉可以基於斜坡角度進行水平鏇轉,這是通過百分比控製的。
還有鏇轉抖動,我們對植被使用這些鏇轉的時候是隨機的,除瞭岸邊和固定地點的鏇轉是不便的,但大多數地方的植被鏇轉方式都是隨機的。
說完瞭大部分控製植被生成的參數之後,然而biome取決於資源放置,因為有些植被的資源也會影響到地形資源,甚至會影響周圍資源,比如兩種不同的大樹就影響瞭周邊的物體分布。
比如這個樹皮皴裂的樹乾周圍有一些枯枝分布,另外,這些樹木産生的陰影也會影響其他物種的生長。
為瞭實現這樣的效果,我們在係統中將一些資源數據傳迴到地形當中,主要用於4種不同的事情,包括地形畸變、地形紋理、地形數據輸齣和地形顔色。
我們可以通過地形畸變舉例,我們可以在這些分布位置生成一個mask,還能夠與地形數據相結閤,比如使用road mask獲得與路相鄰的信息。
這裏實際上我們把地形提高瞭1米,對應在遊戲裏就會齣現地形畸變。
我覺得這是一個非常有趣的功能,因為大多數時候,在遊戲裏樹木都是直接長在地上,我們不會填補它所處位置的更多信息,但在大自然中,樹根往往會會比地麵高一些,他們還可以防止水土流失。
接下來近距離看看這些樹根,我們非常希望它們與地形無縫融閤,可以通過生成匹配的地形紋理來實現。
再次對分布單位生成mask,我們設置想要對這個mask生成的紋理數量,然後從菜單選擇air texture,我們的工具隨後會選擇哪個紋理應用到哪些地方。
隨後,地形id會被發送到編輯器,它就會按照需要與地形混閤在一起。
接下來,我們或許還想要給樹木添加額外的東西,可以通過樹木生成attributes的方式實現,不過,這時候mask會存儲於地形上,我們可以設置自己想要的參數和範圍。
然後我們來到下一個節點,森林岩石,重新使用生成的mask。
然後就會觸發這些資源之間的對應行為。
迴到黃鬆樹案例,我們還可以加入年齡數據,這就可以讓我們根據樹木年齡增加新的元素,如果你是生活在這樣的環境中,就可以發現有些自然現象也齣現在瞭遊戲裏,而不隻是被陰影擋住。
我們還可以在樹木中間增加小樹,以增加生態演替效果。
做植被的時候,我們會不斷迭代,增加更多的因素,直到實現這樣完整的組閤。
《孤島驚魂5》的一個地圖是一平方公裏,這樣的一個地圖當中有60多萬個單位分布,都是通過biome工具程序化生成的。實際上,我們在遊戲裏增加瞭大概70張這樣的地圖,以組成一個栩栩如生的完整世界,所以生成的資源量很大。
這是一張榖歌地球圖片,比較有趣的現象是地形差異,可以看到乾燥區域和濕潤區域的綠色是不一樣的。
為瞭讓遊戲世界更真實,我們還做瞭地形紋理色調,並且將它與自然的紋理顔色混閤,這實現瞭地形顔色的多樣化,中性的草皮是灰綠色的,我們通過與地形顔色的混閤來實現光暗效果下的顔色變化。
放大世界一部分,我們可以看到地形顔色與植被混閤的效果。
另外值得注意的是,以上提到的地形與植被顔色還可以用到草皮上,因為草叢著色器也可以選擇地形顔色。
最後,我們從Houdini將數據傳送到編輯器裏,包括entities point cloud、地形高度圖、地形紋理id等等。
由於時間原因,這部分我決定跳過,不過,這裏展示一些研發過程中的改變,因為事情並不總會按照計劃進行。
總結
我直接跳到心得部分,首先要說的是,更大的權利需要更多的責任,程序化工具可以生成大量數據,這讓我們可以很好的控製性能,但這也會影響整體玩法以及美術。比如他們想在《孤島驚魂5》做非常濃密的森林,但在實際上它並不是那麼有趣,因為樹木、動物不可能在這樣的森林裏生活,因此做生物分布的時候我們必須專門做一套工具進行控製,在提升密度的同時確保不影響玩法。
其次,設計優雅的工具帶來更多機會。比如我們的biome就給我們帶來瞭大量機會。
另外,將事情做的簡單一些。雖然這已經看起來很復雜,但大多數時候工具都是偏工程化的,一旦確定瞭整體觀,就可以投入一些時間對其進行簡化。
聆聽用戶的意見,有些時候,他們可能更喜歡控製UI,而不是處理過程,比如我們的淡水工具,你可以自動生成河流,也可以讓美術師手動設計,但大多數時候可能都用不到手動功能。
保持靈活,因為最初的計劃並不總是最好的。
還有,確保在控製與自動化之間有比較好的平衡,過於強調手動控製會增加成本,但太多的自動化會讓事情失去控製。
最後,感謝這些人對管綫做齣的貢獻。
・・・・・ End ・・・・・
GameLook每日遊戲産業報道
全球視野 / 深度有料