角色控制器庫 (CCL) 是一個模組化框架,用於通過屬性和 Luau 腳本構建角色的移動和行為。這種架構用靈活、可擴展的角色機制系統取代了僵化的 Humanoid 狀態機。
能力
能力評估角色可以做什麼,例如跑步、跳躍、攀爬和游泳的能力。CCL 能力動態確定角色可以做什麼以及如何響應玩家輸入,而不是依賴於固定的引擎定義角色狀態,如 Enum.HumanoidStateType 中的那些。
結構上,能力是一個自包含的 Luau 表,主要指定以下內容:
| 表字段 | 目的 |
|---|---|
| Name | 分配給 標籤 位的名稱,以便 條件 和 衝突 可以引用該能力。多個能力定義可以使用相同的名稱。ModuleScript 名稱決定唯一的配置鍵。 |
| Labels, TimedLabels | 共享 64 位掩碼中的命名位,作為能力之間的協調總線;參見 標籤。 |
| StartsWhen, RunsWhile | 定義何時啟動能力和何時保持其運行的條件;參見 條件。 |
| Blocks, Stops, Suspends, ExclusiveGroup | 如何處理無法同時啟用的能力之間的 衝突。 |
| Input | 觸發能力的輸入。CCL 將其注入到 StartsWhen 中,當您省略 RunsWhile 時,將其用作默認的持續條件;參見 輸入。 |
| Config, State | 每個能力註冊的默認配置值和複製狀態。回調從 abilityCtx.Config 讀取配置,並通過 abilityCtx.State 讀取或寫入複製狀態。 |
| OnSetup, OnStart, OnStop, OnUpdate, OnTeardown | 能力的實際行為被編寫的生命週期回調;參見 回調。 |
標籤
標籤 是共享 64 位掩碼中的命名位,作為能力之間的協調總線。基本上:
- 一個活動的能力 廣播 其 Labels 和 TimedLabels 到世界掩碼。
- 能力 衝突 定義在啟用時被阻止、停止或暫停的 其他 能力。
在以下設置中,當 Running 活動時,"CanFallDown" 標籤被廣播到世界掩碼。具有其 條件 的 FallingDown 能力 StartsWhen = All( "CanFallDown", "Stunned" ) 自動成為候選者,但 "Stunned" 也必須在 FallingDown 發生之前廣播到世界掩碼。
local AvatarAbilities = require("@rbx/AvatarAbilities")
local Identifiers = AvatarAbilities.Identifiers
local Ability = Identifiers.Ability
local Rule = AvatarAbilities.Rule
local Sensor = Identifiers.Sensor
local All, Not = Rule.All, Rule.Not
local Running: AvatarAbilities.AbilityDefinition = {
Name = Ability.Running,
Labels = { "CanFallDown" }, -- 能力活動時廣播的標籤
StartsWhen = Sensor.Ground,
RunsWhile = Sensor.Ground,
}local AvatarAbilities = require("@rbx/AvatarAbilities")
local Identifiers = AvatarAbilities.Identifiers
local Ability = Identifiers.Ability
local Rule = AvatarAbilities.Rule
local Sensor = Identifiers.Sensor
local All, Not = Rule.All, Rule.Not
local FallingDown: AvatarAbilities.AbilityDefinition = {
Name = Ability.FallingDown,
StartsWhen = All( "CanFallDown", "Stunned" ), -- 啟動能力所需的標籤
Blocks = { Ability.Running }
}標籤也可以使用 TimedLabels 字典以 定時 方式廣播或消耗。
| 鍵 | 描述 |
|---|---|
| TimedLabels.OnStart | 包含標籤(鍵)和相關持續時間的字典。當能力啟動時,標籤會被廣播,並在其持續時間結束時自動過期。例如,OnStart = { Dashing = 1 } 在能力啟動時廣播 Dashing 標籤 1 秒。 |
| TimedLabels.OnStop | 包含標籤(鍵)和相關持續時間的字典。當能力停止時,標籤會被廣播,並在其持續時間結束時自動過期。例如,OnStop = { DashCooldown = 2 } 在能力停止時廣播 DashCooldown 標籤 2 秒。 |
| TimedLabels.Consumes | 在能力啟動時要移除(消耗)的標籤列表。例如,如果一個格鬥遊戲允許玩家在阻擋對手攻擊後進行反擊,則 CounterAttack 能力可能包含 StartsWhen = "AfterBlock" 和 TimedLabels = { Consumes = { "AfterBlock" } } 以防止 CounterAttack 能力的雙重觸發。 |
local AvatarAbilities = require("@rbx/AvatarAbilities")
local Identifiers = AvatarAbilities.Identifiers
local Rule = AvatarAbilities.Rule
local Sensor = Identifiers.Sensor
local All, Not = Rule.All, Rule.Not
local Dash: AvatarAbilities.AbilityDefinition = {
Name = "Dash",
StartsWhen = All( Sensor.Ground, Not("DashCooldown") ),
RunsWhile = "Dashing",
TimedLabels = {
OnStart = { Dashing = 1 },
OnStop = { DashCooldown = 2 },
},
}條件
條件 是一個或多個 標籤、傳感器 或輸入引用,用於 StartsWhen 和 RunsWhile。條件在運行時編譯為位掩碼操作,評估是整數數學 — 沒有表遍歷和沒有字符串比較。
| 目標 | 語法 | 示例 |
|---|---|---|
| 一個必需的條件。 | StartsWhen = Sensor.Ground | |
| AND 邏輯,當 所有 標籤存在於世界掩碼中且 所有 傳感器處於活動狀態時。 | All() | StartsWhen = All( "CanFallDown", "Stunned" ) |
| OR 邏輯,當 任何 標籤存在於世界掩碼中或 任何 傳感器處於活動狀態時。 | Any() | StartsWhen = Any( "WallClimbing", "Climbing" ) |
| 否定,使得標籤 不能 存在於世界掩碼中,且傳感器 不能 處於活動狀態。 | Not() | RunsWhile = Not("Stunned") |
條件評估可以結合以實現更複雜的邏輯,例如 All() 鏈接加上 Not() 以指示一個傳感器必須處於活動狀態,而一個標籤必須不存在:
local AvatarAbilities = require("@rbx/AvatarAbilities")
local Identifiers = AvatarAbilities.Identifiers
local Rule = AvatarAbilities.Rule
local Sensor = Identifiers.Sensor
local All, Not = Rule.All, Rule.Not
local Dive: AvatarAbilities.AbilityDefinition = {
Name = "Dive",
StartsWhen = All( Sensor.WaterSurface, Not("Recovering") ),
}衝突
某些能力在另一個能力活動時無法啟用;例如,角色在游泳時無法跳躍,並且在下墜時無法跑步。引擎在能力的定義內以聲明方式解決這些衝突:
| 衝突鍵 | 目的 |
|---|---|
| Blocks | 當擁有的能力處於活動狀態時,列出的其他能力無法啟動。例如,ScopeAim 能力可能包含 Blocks = { Ability.Running, Ability.Jumping } 以防止角色在仔細瞄準武器的瞄準鏡時跑步或跳躍。 |
| Stops | 當擁有的能力啟動時,列出的其他能力 強制停止 並必須重新觸發。例如,Hover 能力可能包含 Stops = { Ability.Running } 以在角色開始懸浮時立即停止其跑步動作。 |
| Suspends | 當擁有的能力啟動時,列出的其他能力 暫停,然後在擁有的能力停止時 自動恢復。例如,自定義衝刺能力可能包含 Suspends = { Ability.Running },以便在衝刺開始時跑步 🄐 暫停,🄑 在衝刺中被阻止,並在衝刺停止時 🄒 恢復。 |
另一個獨特的衝突鍵是 ExclusiveGroup,它將多個能力放入一個組中,每個能力都有一個 Priority 值。每組中只能有一個能力處於活動狀態,且優先級較高者獲勝。然而,如果挑戰者聲明 Stops 針對持有者的名稱/標籤,則無論優先級如何,它都會獲勝。
在以下設置中,三個能力(Sprinting、Crouching、Stagger)被添加到 Locomotion 獨佔組中。Sprinting 具有最高優先級(200),因此它勝過 Crouching(100),這兩者永遠不會同時運行。然而,Stagger 強制停止衝刺 (Stops = { Ability.Sprinting }),因此即使其優先級(150)較低,它也可以中斷並超越 Sprinting。
local AvatarAbilities = require("@rbx/AvatarAbilities")
local Identifiers = AvatarAbilities.Identifiers
local Ability = Identifiers.Ability
local Rule = AvatarAbilities.Rule
local Sensor = Identifiers.Sensor
local All, Not = Rule.All, Rule.Not
local Sprinting: AvatarAbilities.AbilityDefinition = {
Name = Ability.Sprinting,
ExclusiveGroup = { Name = "Locomotion", Priority = 200 },
}
local Crouching: AvatarAbilities.AbilityDefinition = {
Name = Ability.Crouching,
ExclusiveGroup = { Name = "Locomotion", Priority = 100 },
}
-- 低優先級的能力可以通過停止高優先級的能力來覆蓋它
local Stagger: AvatarAbilities.AbilityDefinition = {
Name = "Stagger",
ExclusiveGroup = { Name = "Locomotion", Priority = 150 },
Stops = { Ability.Sprinting },
}輸入
能力的 Input 定義指定用於嘗試激活能力的輸入。它接受配置輸入行為、動作槽和可選觸控按鈕圖標的鍵值對。
local AvatarAbilities = require("@rbx/AvatarAbilities")
local Identifiers = AvatarAbilities.Identifiers
local Rule = AvatarAbilities.Rule
local Sensor = Identifiers.Sensor
local All, Not = Rule.All, Rule.Not
local Dash: AvatarAbilities.AbilityDefinition = {
Name = "Dash",
Input = { InputName = "Dash", Mode = "Press", ActionSlot = 5 }
}InputName 是邏輯名稱,而不是鍵。CCL 生成一個輸入傳感器,並始終將其添加到 StartsWhen 中。不要自己將 Rule.Input 添加到 StartsWhen。
Mode 定義此輸入將如何被解釋:
模式 行為 用例 Press 當按下輸入時嘗試激活能力。自動注入到 StartsWhen 條件中。 離散行動,如衝刺、攻擊和投擲。 Hold 當按住輸入時能力運行;釋放時停止,當生成的輸入傳感器是 RunsWhile 條件時。 持續行動,如衝刺、瞄準和阻擋。 Toggle 每次按下切換能力的開啟或關閉,當生成的輸入傳感器是 RunsWhile 條件時。 切換的姿勢或動作,如蹲下或懸浮。 Repeat 類似於 Hold,但每個循環重新觸發。 自我停止的行動,並且在按住時可以重新觸發。 ActionSlot 定義一個 動作槽,該槽與 輸入動作系統 中的一組 InputActions 和 InputBindings 相關聯。
幾個動作插槽輸入綁定是由 Roblox 預定義的,未來的 輸入動作管理器 將允許您根據需要重新配置動作插槽的默認輸入綁定。將 ActionSlot 設置為 0 將選擇下一個可用的空插槽。在移動設備上,插槽 1-7 會填充到屏幕上的按鈕(見下圖)。
插槽 鍵盤和滑鼠 遊戲手把 觸控 默認分配 1 Space ButtonA ① 跳躍 2 LeftShift ButtonL1 ② 衝刺 3 LeftControl ButtonB ③ 蹲下 4 R ButtonX ④ 5 MouseLeftButton ButtonR2 ⑤ 6 Q ButtonY ⑥ 7 X ButtonR1 ⑦ 8 C ButtonL2 9 F DPadLeft 10 G DPadRight 11 V DPadDown 
CustomIcon、CustomIconActive 和 CustomIconInvalid 分別指定能力閒置、活動或不可用時的觸控按鈕的 Roblox 資產 ID。
當您省略 RunsWhile 時,CCL 使用生成的輸入傳感器作為持續條件。當您定義 RunsWhile 時,它會替換該默認值。對於必須在其輸入變為非活動時停止的 Hold 或 Toggle 能力,請直接在自定義條件中包含 Rule.Input 哨兵。Rule.Input 是一個值,而不是一個函數:
local AvatarAbilities = require("@rbx/AvatarAbilities")
local Rule = AvatarAbilities.Rule
local Sensor = AvatarAbilities.Identifiers.Sensor
local All, Input, Not = Rule.All, Rule.Input, Rule.Not
local Glide: AvatarAbilities.AbilityDefinition = {
Name = "Glide",
Input = { InputName = "Glide", Mode = "Hold", ActionSlot = 6 },
StartsWhen = Not(Sensor.Ground),
RunsWhile = All(Not(Sensor.Ground), Input),
}傳感器
傳感器 是一個有關世界的命名值,引擎為您讀取。您通常會讀取傳感器而不是寫入它們。為了方便起見,幾個傳感器已經預先註冊:
| 傳感器 | 描述 |
|---|---|
| Sensor.Ground | 站在一個表面上 |
| Sensor.IsMoving | 正在施加移動輸入 |
| Sensor.MoveInput | 移動向量本身 |
| Sensor.Ceiling | 某物在正上方 |
| Sensor.Climb | 可攀爬的表面在範圍內 |
| Sensor.Water / Sensor.WaterSurface | 在水中 / 在水面上 |
| Sensor.Sit | 坐著 |
| Sensor.Tipped | 翻倒了 |
| Sensor.Tool | 持有一個 Tool |
| Sensor.LookDirectionInput | 命令的視覺方向 |
| Sensor.RotateToLookDirectionInput | 角色是否應該旋轉到命令的視覺方向 |
回調
能力 回調函數 讓您編寫特定行為:
雖然您在伺服器上註冊自定義能力,但它們的回調在預測的客戶端模擬和權威的伺服器模擬中運行。保持回調行為的確定性,以便兩個模擬產生相同的結果。
| 回調 | 運行 | 用例 |
|---|---|---|
| OnSetup(managerCtx, abilityCtx) | 一次,當能力被註冊時。 | 緩存引用,初始化狀態等。 |
| OnStart(managerCtx, abilityCtx, hadLabel) | 每次激活能力時。 | 應用效果,例如衝擊。hadLabel() 函數報告在激活開始時是否存在指定的標籤,在衝突解決之前。 |
| OnUpdate(managerCtx, abilityCtx) | 每個活動幀。 | 持續工作,例如計時器或每幀的力量。 |
| OnStop(managerCtx, abilityCtx) | 每次停用,無論是自願還是強制。 | 撤消 OnStart() 所做的事情。 |
| OnTeardown(managerCtx, abilityCtx) | 在能力移除時。 | 斷開連接,銷毀實例等。 |
每個回調函數的第一個參數 managerCtx 是一個 ManagerContext 對象,具有共享的角色和管理屬性,包括:
- managerCtx.AbilityManager — 管理器的簡化視圖,以便能力可以在其自己的回調中添加、移除和查詢能力。
- managerCtx.BodyParts — 角色的身體部件,具有每個肢體開啟和關閉碰撞的幫助器。
- managerCtx.RootCFrame — 根部件的 CFrame,在幀開始時快照一次,以便回調不必各自去獲取它。
- managerCtx.RootLookVector — 角色根部件面對的方向。
- managerCtx.RootUpVectorY — 根部件的上向量的 Y 分量。
- managerCtx.TaskSynchronize() — 在啟用並行回調支持時,在訪問 DataModel 之前同步回調。當前,OnUpdate 不在並行上下文中運行,因此此函數沒有效果。完整的並行 Luau 支持計劃在未來的更新中實現。
第二個參數 abilityCtx 是一個 AbilityContext 對象,具有引擎管理的當前能力註冊的表:
- abilityCtx.Config — 此能力註冊的只讀配置值。
- abilityCtx.State — 可變狀態,通過 DataModel 複製。 伺服器權威 在回滾和重新模擬期間恢復這些值。
- abilityCtx.Local — 不複製或參與回滾的可變臨時狀態。
將自定義回調數據存儲在 abilityCtx.State 或 abilityCtx.Local 中。直接寫入自定義字段到 abilityCtx 是錯誤的。