Bomber
概述
Quantum炸彈人範例附有完整的源程式碼,並且展示了在Quantum中如何組建炸彈人遊戲的遊戲遊玩。
下載
版本 | 發布日期 | 下載 | ||
---|---|---|---|---|
2.1.6 | 2023年7月18日 | Quantum 炸彈人 2.1.6 組建 268 |
在您開始之前
為了以線上多人玩家模式來運行範例,首先在Photon引擎儀表板中建立一個Quantum應用程式帳號,然後貼上它到PhotonServerSettings
資產中的AppId
欄位。
然後在場景選單中載入Menu
場景並且按下Play
。
技術資訊
- Unity:2021.3.13f1或更高版本
- 平台:PC (Windows)
聚焦點
技術
- 為了從上到下的網格基礎遊戲而量身打造的自訂
Movement
元件及系統 - 半程序化的地圖生成以及強化物生成
- 角色客製化
- 基於時間的爆炸擴散
- 零事件模擬方法
- 相對簡潔的ECS模擬架構
遊戲遊玩
- 大亂鬥炸彈人
- 放置炸彈
- 修改炸彈數量、爆炸範圍以及移動速度的形式的強化物。
控制
- WASD以移動
- 空白鍵以放置炸彈
單元格
Cell
是一個DSL定義的架構,其以CellType
旗標的形式來持有一個單一值。為了更方便地存取及修改這些值,該架構已使用Cell.User.cs
指令碼中的屬性及方法來進行擴展。
各個單元格都知道目前位於其位置的物件的類型,但是它本身沒有任何參照到實體。當一個系統迭代一個實體,它檢查單元格中是否有任何有興趣的內容。舉例而言,如果單元格IsBurning
,那麼它將在它負責的元件上觸發適當的回應。
因為CellType
是一個旗標,所有屬性都可以架構為位元方式的操作,這使得它們非常高效。
網格
Grid
是一個常規的CSharp類別,其含有GridSettings
架構、Cell
架構的陣列及一個指標。
幀.使用者
有了Grid
定義為常規類別,以及在它的Frame.User
中有執行個體,因此可以透過常規的Frame.XYZ
API來讓其可用,同時將所有相關方法封裝在Frame.Grid.XYZ
之中。
網格作為常規類別的缺點時它的資料位在常規DSL生成的記憶體之外。因此必要的是手動地處理初始化、序列化、複製、清除及拋棄資料。這是透過掛鉤到Frame.User
內部的下列方法來完成的:
InitUser()
:最初建立幀時被調用一次。FreeUser()
:幀被銷毀時被調用。CopyUser()
:當先前的幀狀態被複製到下一個幀之中時被調用。SerializeUser()
:當幀被序列化時被調用(比如針對延遲加入者作為一個夥伴快照)。DumpFrameUser()
:當停止同步發生時被調用。
網格設定
可在GridSettings
架構中找到如何生成及設定網格的資訊。使用其中持有的資訊,可以在運行階段設定1D陣列,並且以固定及可破壞的方塊的位置來填入它,以及推測SpawnPoints
的位置。
單元格陣列,或稱為網格
網格單元格被內含在Cells
的1D陣列之中。該原理與圖塊地圖路徑尋找器技術範例中的圖塊地圖資產相同。DSL支援1D陣列;然而,DSL需要在編譯時刻知道陣列的大小,因為網格是在運行階段基於玩家請求的大小而生成的,所以必須以不同的方式來處理。
陣列是在運行階段透過掛鉤到Frame.User
中的InitUser()
方法之中來建立的。
Grid
之中的1D陣列透過掛鉤到Frame.User
內部的CopyUser()
及SerializeUser()
方法,來與預測—復原及延遲加入序列化相容。
效能
雖然一個Cell
只含有一個位元組旗標,但是透過複製幀來完成的的讀寫量可能會造成嚴重的效能瓶頸。為了預防這種情況,在Grid.cs
中已經針對網格及其單元格來定義了多個取得-設定方法。這些方法使用者指標數學以將指標傳回單元格,因此允許直接讀取及寫入架構。
廣譜設定及清除
有兩種系統來寫入記憶體到網格:
SetBroadphaseSystem
:在所有遊戲遊玩系統 之前 運行,並且基於其目前含有的實體來設定單元格類型。ClearBroadphaseSystem
:在所有遊戲遊玩系統 之後 運行,並且針對將被銷毀的實體來清除單元格中的資訊。
輸入
輸入架構由5個按鈕組成。
C#
input {
Button MoveUp;
Button MoveDown;
Button MoveLeft;
Button MoveRight;
Button PlaceBomb;
}
這是輸入架構中可以採用的最精簡的形式。雖然Button
類型在模擬中佔用1個位元組,但是它在纜線上被壓縮成1位元。
為了準備遊戲遊玩系統將耗用的玩家輸入,InputSystem
使用移動按鈕來建構一個Direction
,並且基於PlaceBomb
按鈕值在AbilityPlaceBomb
中設定WantsToPlaceBomb
布林值。
炸彈人
Bomber
元件是一個旗標元件以識別及篩選實體。
因此,關聯的BomberSystem
相對簡單,因為它的唯一工作是檢查一個炸彈人類型實體在給定的Update()
期間是否正站在一個燃燒的單元格上。
C#
public override void Update(Frame f, ref BomberFilter filter)
{
var gridPosition = filter.Transform->Position.RoundToInt(Axis.Both);
var isInvincible = false;
#if DEBUG
// Used for debugging purposes
isInvincible = f.RuntimeConfig.IsInvincible;
#endif
if (isInvincible == false && f.GetCellRef(gridPosition).IsBurning)
{
// Death animation is triggered from OnEntityDestroyed
f.Destroy(filter.Entity);
}
}
炸彈
炸彈是暫時實體,其由一個玩家動作來建立,並且在它們的Timer
到期時導致一個爆炸。
有兩個系統與Bomb
元件互動:
AbilityPlaceBombSystem
:檢查玩家是否已經按下PlaceBomb
按鈕,以及是否符合條件來放置一個。BombSystem
:開始在炸彈上的Timer
,處理連鎖反應,並且在銷毀炸彈時觸發一個爆炸(因為計時器到期或另一個炸彈的爆炸碰到它)。
爆炸
爆炸持續一段確定的時間。因此它們需要作為一個實體而存在,而非只是一個射線投射。ExplosionSystem
處理爆炸生命週期,以及從單元格到單元格的爆炸擴散。
一個爆炸實體由兩個元件組成:
Explosion
:一個元件用作為一個旗標元件,以及持有關於爆炸設置的資訊。Timer
:計時器用於計算爆炸擴散到下一個相鄰單元格之前的剩餘時間。
強化物
透過兩個主要的元件來提供強化物功能性
PowerUp
:以類型及修改器數量,來定義一個強化物;以及,PowerUpManager
:持有可生成強化物的清單以及生成機率。
當從網格中清除一個可銷毀方塊時,有機會生成強化物。在方塊銷毀時,PowerUpManager
將被告知新的被清除的位置。PowerUpManagerSystem
迭代新的可用的地點,並且如果該單元格是空的且目前沒有著火的話,將嘗試在其上生成一個隨機的強化物。
移動
單元格內部的移動是不受限制的,並且讀取網格以確定允許角色前往的地方。
方向
Direction
是一個位元組旗標,其含有目前被按下的移動按鈕。
移動元件
Movement
元件追蹤幀之間的相關移動值。
FP CurrentSpeed
:目前的角色移動的速度。FP MaxSpeed
:角色被允許移動的最大速度。Boolean IsMoving
:追蹤最後的移動輸入是否導致一個移動。Boolean LastMoveWasHorizontal
:追蹤最後的移動的方向。Direction LastNewInput
:在垂直及水平方向追蹤玩家提供的最後的輸入。Direction CurrentInput
:目前被按下的移動方向。FPVector2 MoveDirection
:最後的移動方向FP StartRotation
:在方向改變之前的最後的查看旋轉。FP TargetRotation
:在方向改變之後的角色應該有的查看旋轉。int RotationStartTick
:開始向新的方向旋轉的刷新。FP RotationDuration
:一個旋轉應該有的最大總持續時間。FP RotationTimeMultiplier
:為了在分配的時間內達到一個完整的旋轉所需的旋轉速度乘數。
移動系統
移動系統滿足了三個核心功能性:
- 基於目前被按下的移動鍵來計算可能的移動(
GetMovementResult()
)並且傳回一個含有值的MoveResult
架構。 - 更新目前的移動速度(
UpdateCurrentSpeed()
) - 移動角色(
UpdateMovement()
) - 旋轉角色(
UpdateRotation()
)
MovementSystem
執行兩個功能以提供一個在網格上的平順連續的對角線的移動:
CanMoveInDirection()
負責角落滑行。當按下一個對角線的方向時,這讓一個角色可以平順地在角落周圍移動。GetMoveVector()
含有一個方向切換以替換首先檢查的方向(垂直或水平)。這允許角色來連續地在網格上沿著對角線移動。
移動結果
MoveResult
是一個公用程式架構。它針對角色將在其上移動的網格單元格,來持有目前的Movement.CurrentInput
的處理結果。因為這些值不作為幀狀態的一部分來使用,它被定義為一個常規的CSharp架構,而不是在DSL之中。
FPVector2 Direction
:所需的移動方向。FP MaxDistance
:角色在所需方向上能夠移動的最大可能距離。FPVector2 LookDirection
:作為這個移動的結果,角色將查看的方向。FP RotationTimeMultiplier
:角色應該基於它目前的查看方向及所需的查看方向之間的角度,來切換它們的查看方向的速度,以在預先定義的時間量之內完成旋轉。
第三方資產
炸彈人範例包含由其各自的創作者提供的多個資產。您可以在他們各自的網站上為自己的專案獲得完整的套件:
- Archanor VFX的史詩級Toon FX
- Judah4的針對Unity UI的HSV顏色採集器
重要事項 :為了在商業專案中使用它們,需要從各自的創作者來購買授權。
Back to top