目錄
概念及功能
網格對象(Grid Object) 和世界對象(World Object)
工作流程
-
概念及功能
TrinityCore 的 Grid 系統是一套復雜的地圖分區管理機制,其核心目標是通過動態管控游戲世界的區域狀態和對象生命周期,在保證玩家體驗的同時最大化服務器性能。它具有以下功能:
-
地圖劃分與定位
TrinityCore 將每一張地圖(Map)都劃分成 64*64 的小方塊,即網格(Grid),每個 Grid 的大小是 533.33 碼。網格的坐標從右下角 (0,0) 到左上角 (63,63),以 (32,32) 為中心點。這種劃分方式便于服務器和客戶端對地圖進行管理和定位,例如可以在GM模式下使用 “.go grid 48,18” 類似命令跳到當前地圖編號為 (48,18) 的格子。 -
資源加載與卸載
客戶端和服務端均按 Grid 為單位進行地圖資源的加載和卸載。當角色在地圖中移動時,客戶端只加載角色附近的 Grid,當角色走到一個 Grid 邊界時,再新加載相鄰的 Grid,同時卸載遠離角色的 Grid,從而有效控制內存占用。服務端也是如此,只有當某個 Grid 有角色進入時,才會將其標記為活躍狀態,加載其中的動態信息,如怪物、NPC、礦點等;當 Grid 內沒有活躍角色且超過一定時間后,會將其標記為不活躍狀態,卸載其中的動態對象,回收 Grid。 -
對象管理
Grid 用于管理其中的各種對象,包括網格對象(grid object)和世界對象(world object)。Grid 類提供了一系列方法來插入、移除和統計這些對象,如add_grid_object
方法用于將一個對象插入到網格中,get_world_object_countingrid
方法用于獲取網格中世界對象的數量。 -
尋路支持
Grid 與尋路功能相關,TrinityCore 可以利用導航網格(Grid)做尋路,通過 Detour 庫等實現角色在地圖上的路徑規劃,確保角色能夠在網格劃分的地圖上順利找到目標位置。
-
-
網格對象(Grid Object) 和世界對象(World Object)
-
世界對象(World Object)
是游戲世界中所有 “可交互實體” 的基類(WorldObject
),代表游戲中具有獨立存在意義的實體,例如角色(Player)、NPC(Creature)、物品(Item)、動態物體(GameObject,如箱子、門)等。世界對象(World Object)是游戲邏輯的核心載體,擁有獨立的屬性(如位置、方向、狀態)和行為(如移動、戰斗、交互),并直接參與游戲玩法(如任務、戰斗、交易)。- 世界對象負責實現具體的游戲邏輯,例如:處理玩家輸入(移動、技能釋放),NPC 的 AI 行為(巡邏、攻擊、對話),物品的拾取、使用效果,碰撞檢測、交互判定(如點擊 NPC 觸發對話),等等。
- 世界對象生命周期與實體本身綁定:例如玩家登錄時創建,下線時銷毀;NPC 被刷新時創建,被刪除(如死亡后消失)時銷毀。
- 當世界對象(如角色移動)從一個 Grid 進入另一個 Grid 時,其對應的網格對象會從舊 Grid 移除,添加到新 Grid 中。
-
世界對象在整個游戲世界中具有唯一標識(GUID),可被全局查詢和引用。
-
世界對象是基類,派生類包括Corpse、
Creature
、DynamicObject、GameObject
、Player
、AreaTrigger、SceneObject、Conversation等,每個派生類都有獨特的屬性和方法(如Player
有背包系統,Creature
有 AI 組件)。
-
網格對象(Grid Object)
是與 Grid 網格綁定的 “輔助管理對象”(GridObject
),主要用于銜接世界對象與 Grid 系統,負責將世界對象 “錨定” 到具體的網格中,以便 Grid 系統對其進行定位、加載 / 卸載和區域管理。它更像是世界對象在 Grid 系統中的 “代理” 或 “索引”,本身不直接參與游戲邏輯,僅用于 Grid 內部的管理和查詢。- 網格對象主要服務于 Grid 系統的管理需求,例如:記錄世界對象在 Grid 中的位置偏移,輔助 Grid 快速定位實體;作為 Grid 內部的 “容器項”,參與 Grid 的對象列表維護(如添加、移除、遍歷);觸發 Grid 的狀態變化(如當 Grid 中首個世界對象進入時,標記 Grid 為 “活躍” 并加載資源)。
- 網格對象生命周期與 Grid 綁定:當一個世界對象進入某個 Grid 時,Grid 會為其創建對應的網格對象;當世界對象離開 Grid 或 Grid 被卸載時,網格對象會被銷毀。
- 網格對象僅存在于所屬 Grid 中:每個網格對象嚴格屬于一個 Grid,用于在該 Grid 內標記世界對象的存在,方便 Grid 快速定位其中的所有實體。
- 網格對象是模板類(
GridObject<T>
),其中T
通常是WorldObject
的派生類(如GridObject<Creature>
),它內部持有一個指向對應世界對象的指針,實現 Grid 與世界對象的關聯。
-
-
工作流程
????????工作流程分為初始化與地圖劃分、Grid 激活與對象加載、活躍狀態管理、Grid 失活與資源回收四個階段,各階段緊密銜接,形成完整的閉環邏輯。
????????一、初始化與地圖劃分:構建 Grid 的 “骨架”
????????Grid 系統的工作從地圖(Map)加載開始,當服務器啟動或角色首次進入某張地圖時,系統會先完成 Grid 的基礎構建:
-
地圖元數據加載
從數據庫(如map
表)和地圖資源文件(.adt
等)中讀取地圖的基礎信息,包括地圖 ID、尺寸、地形數據等。每張地圖被視為一個獨立的 “世界區域”,由Map
類實例管理。 -
Grid 網格劃分
按照固定規則將地圖劃分為64×64 的 Grid 網格(共 4096 個 Grid),每個 Grid 的物理尺寸為 533.33 碼(約 133.33 游戲單位)。網格坐標以地圖右下角為原點 (0,0),左上角為 (63,63),形成類似二維數組的索引體系(如 Grid (10,20) 代表第 10 列、第 20 行的網格)。 -
Grid 基礎實例化
為每個 Grid 創建基礎實例(Grid
類對象),此時的 Grid 僅包含坐標信息和空的對象列表,處于 **“未初始化” 狀態 **(不加載任何世界對象,僅作為占位符存在)。這些 Grid 由GridManager
統一管理,通過地圖 ID+Grid 坐標可快速定位。
????????二、Grid 激活與對象加載:從 “休眠” 到 “活躍”
????????Grid 默認處于 “休眠” 狀態,僅當需要響應用戶交互時才被激活。“有玩家角色進入” 是觸發 Grid 激活的核心條件。
-
玩家位置檢測
當角色(Player
對象)通過移動、傳送、復活等方式進入某 Grid 時,系統通過角色坐標計算其所在的 Grid 坐標(如通過Map::GetGridX()
和Map::GetGridY()
方法),并檢查該 Grid 的當前狀態。 -
Grid 狀態切換:從非活躍到活躍
- 若 Grid 處于 “非活躍狀態”(無玩家且未加載對象),系統會將其標記為 “活躍狀態”(Active),并觸發
Grid::Activate()
方法。 - 激活時,Grid 會向
Map
模塊注冊自身,加入 “活躍 Grid 列表”,以便后續接收定期更新(如每 100ms 一次的邏輯幀更新)。
- 若 Grid 處于 “非活躍狀態”(無玩家且未加載對象),系統會將其標記為 “活躍狀態”(Active),并觸發
-
世界對象加載
激活后,Grid 開始加載其內 “應存在” 的世界對象(WorldObject)。- 查詢數據源:根據地圖 ID 和 Grid 坐標,從數據庫(如
creature
、gameobject
表)查詢該 Grid 內的靜態對象(如固定刷新的 NPC、門、礦點)和動態對象(如任務觸發的怪物)。 - 實例化對象:根據查詢結果,創建對應的世界對象實例(如
Creature
、GameObject
),初始化其屬性(位置、方向、狀態、AI 腳本等)。 - 綁定網格對象(GridObject):為每個世界對象創建對應的
GridObject
(網格對象),作為其在 Grid 中的 “代理”,并將GridObject
添加到 Grid 的對象列表(Grid::m_objects
)中。 - 通知周邊系統:對象加載完成后,通知視野管理模塊(讓附近玩家可見)、AI 系統(啟動 NPC 巡邏 / 戰斗邏輯)、事件系統(注冊交互事件,如點擊 NPC 觸發對話)。
- 查詢數據源:根據地圖 ID 和 Grid 坐標,從數據庫(如
????????三、活躍狀態管理:維持對象交互與更新
????????Grid 處于活躍狀態時,核心任務是實時管理其內對象的狀態和交互,確保游戲邏輯正常運行,主要包括以下操作:
-
定期邏輯更新
Grid 會隨服務器的邏輯幀(通常每 100ms 一次)執行Grid::Update()
方法,完成:- 對象狀態同步:更新世界對象的位置、血量、狀態(如 NPC 的巡邏路徑進展、GameObject 的開關狀態)。
- AI 與行為驅動:觸發 NPC 的 AI 邏輯(如檢測玩家進入仇恨范圍、執行技能)、物品的定時消失(如掉落的裝備過期)。
- 事件檢測:檢查對象間的交互(如玩家點擊門、拾取物品),觸發對應的游戲事件(如任務進度更新、成就解鎖)。
-
對象跨 Grid 移動處理
當世界對象(如玩家、移動的 NPC)從當前 Grid 進入相鄰 Grid 時,觸發對象轉移流程:- 舊 Grid 移除對象:原 Grid 通過
Grid::RemoveObject()
方法,將對象的GridObject
從自身列表中移除,并通知舊 Grid(若此時舊 Grid 內無玩家,開始失活倒計時)。 - 新 Grid 添加對象:新 Grid 檢測到角色進入后,若自身處于非活躍狀態則立即激活,然后通過
Grid::AddObject()
方法創建新的GridObject
,將對象納入管理,并同步其狀態到新 Grid 及周邊系統。
- 舊 Grid 移除對象:原 Grid 通過
-
動態對象生成與銷毀
對于臨時產生的對象(如玩家召喚的寵物、技能創建的幻象、任務觸發的怪物),Grid 會在其生成時立即創建GridObject
并納入管理;當對象過期(如寵物消失、幻象時間結束)或被銷毀(如怪物被擊殺)時,Grid 會移除其GridObject
并回收內存。
????????四、Grid 失活與資源回收:從 “活躍” 到 “休眠”
??????? 當 Grid 內不再有角色活動時,系統會逐步卸載資源,釋放服務器內存和 CPU 占用。
-
失活觸發條件
- 所有角色離開該 Grid(如移動到其他 Grid、下線、傳送);
- Grid 內無角色的時間超過閾值(默認約 5 分鐘,可通過配置調整)。
滿足條件后,Grid 被標記為 “待失活狀態”,觸發Grid::Deactivate()
方法。
-
對象篩選與卸載
Grid 會先篩選可卸載的對象,保留必要數據:- 不可卸載對象:角色(
Player
)本身不會隨 Grid 失活卸載(其生命周期與登錄狀態綁定);帶有 “永久保存” 標記的對象(如玩家放置的營地)會保留狀態。 - 可卸載對象:大部分 NPC、GameObject、臨時物品等,會先將狀態同步到數據庫(如 NPC 的刷新時間、已打開的箱子狀態),然后銷毀其實例和對應的
GridObject
。
- 不可卸載對象:角色(
-
Grid 資源回收
- 清空 Grid 的對象列表,釋放與對象相關的臨時數據(如視野緩存、AI 狀態)。
- Grid 從 “活躍 Grid 列表” 中移除,回到 “非活躍狀態”,僅保留基礎坐標信息,進入 “休眠”。
- 若后續有角色再次進入該 Grid,重復 “激活→加載” 流程。
????????五、特殊場景的補充處理
????????Grid 系統針對特殊需求做了優化,確保極端場景下的穩定性:
- 強制激活 / 失活:GM 可通過指令(如
.go grid
、.grid activate
)強制激活某 Grid,用于調試或事件觸發;也可強制失活 Grid 以快速釋放資源。 - 超大對象處理:對于跨多個 Grid 的大型對象(如團隊副本的 Boss 場地),系統會將其關聯到多個 Grid,確保在任何相關 Grid 激活時都能正確加載。
- 動態地圖(如副本):副本地圖的 Grid 生命周期與副本實例綁定,當副本內所有玩家離開并超過超時時間后,整個副本的 Grid 系統會被徹底銷毀,而非僅失活。