角色控制器庫

*此內容是使用 AI(Beta 測試版)翻譯,可能含有錯誤。若要以英文檢視此頁面,請按一下這裡。

角色控制器庫 (CCL) 是一個模組化框架,用於通過屬性和 Luau 腳本構建角色的移動和行為。這種架構用靈活、可擴展的角色機制系統取代了僵化的 Humanoid 狀態機。

啟用 CCL

CCL 是透過 Studio 的 角色設定 視窗 選擇性啟用 的。要啟用它:

  1. 透過 檔案 ⟩ 測試功能 ⟩ AvatarAbilities 角色控制器庫 啟用 CCL 測試版。

  2. 在 角色 標籤中,打開 角色設定。

    在 Studio 工具列中指示的角色設定
  3. 在視窗左側選擇 移動 標籤,然後在 能力 區域中選擇 角色 控制器 庫。

    角色設定視窗中的角色控制器庫切換
  4. 所有標準能力如 跑步、跳躍 和 攀爬 預設為啟用。要在運行時禁用其中任何一項,請取消選中相關的方框。

能力

能力評估角色可以做什麼,例如跑步、跳躍、攀爬和游泳的能力。CCL 能力動態確定角色可以做什麼以及如何響應玩家輸入,而不是依賴於固定的引擎定義角色狀態,如 Enum.HumanoidStateType 中的那些。

結構上,能力是一個自包含的 Luau 表,主要指定以下內容:

表字段目的
Name能力的唯一身份;條件 和 衝突 通過名稱引用它。註冊兩個具有相同 Name 的能力會引發錯誤。對於幾個相似的能力,給每個能力一個不同的 Name,並在 Labels 中共享一個公共 標籤。ModuleScript 名稱決定唯一的配置鍵。
Labels, TimedLabels共享 64 位掩碼中的命名位,作為能力之間的協調總線;參見 標籤。
StartsWhen, RunsWhile定義何時啟動能力和何時保持其運行的條件;參見 條件。
Blocks, Stops, Suspends, ExclusiveGroup如何處理無法同時啟用的能力之間的 衝突。
Input觸發能力的輸入。Input.Mode 控制輸入如何啟動和停止能力;RunsWhile 僅包含世界條件,從不包含輸入本身;參見 輸入。
Config, State每個能力註冊的默認配置值和複製狀態。回調從 abilityCtx.Config 讀取配置,並通過 abilityCtx.State 讀取或寫入複製狀態。
OnSetup, OnStart, OnStop, OnUpdate, OnTeardown能力的實際行為被編寫的生命週期回調;參見 回調。

標籤

標籤 是共享 64 位掩碼中的命名位,作為能力之間的協調總線。基本上:

  • 一個活動的能力 廣播 其 Labels 和 TimedLabels 到世界掩碼。
  • 能力 條件 (StartsWhen, RunsWhile) 測試 世界掩碼並作出反應。
  • 能力 衝突 定義在啟用時被阻止、停止或暫停的 其他 能力。

在以下設置中,當 Running 活動時,"CanFallDown" 標籤被廣播到世界掩碼。具有其 條件 的 FallingDown 能力 StartsWhen = All( "CanFallDown", "Stunned" ) 自動成為候選者,但 "Stunned" 也必須在 FallingDown 發生之前廣播到世界掩碼。

Running Ability
local AvatarAbilities = require("@rbx/AvatarAbilities")
local Identifiers = AvatarAbilities.Identifiers
local Ability = Identifiers.Ability
local Rule = AvatarAbilities.Rule
local Sensor = Identifiers.Sensor
local All, Any, Not = Rule.All, Rule.Any, Rule.Not
local Running: AvatarAbilities.AbilityDefinition = {
Name = Ability.Running,
Labels = { "CanFallDown" }, -- 能力活動時廣播的標籤
StartsWhen = Sensor.Ground,
RunsWhile = Sensor.Ground,
}
FallingDown Ability
local AvatarAbilities = require("@rbx/AvatarAbilities")
local Identifiers = AvatarAbilities.Identifiers
local Ability = Identifiers.Ability
local Rule = AvatarAbilities.Rule
local Sensor = Identifiers.Sensor
local All, Any, Not = Rule.All, Rule.Any, 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 能力的雙重觸發。
Timed Labels
local AvatarAbilities = require("@rbx/AvatarAbilities")
local Identifiers = AvatarAbilities.Identifiers
local Rule = AvatarAbilities.Rule
local Sensor = Identifiers.Sensor
local All, Any, Not = Rule.All, Rule.Any, 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, Any, Not = Rule.All, Rule.Any, 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 }),因此它可以中斷並超越 Sprinting,即使它的優先級(150)較低。

local AvatarAbilities = require("@rbx/AvatarAbilities")
local Identifiers = AvatarAbilities.Identifiers
local Ability = Identifiers.Ability
local Rule = AvatarAbilities.Rule
local Sensor = Identifiers.Sensor
local All, Any, Not = Rule.All, Rule.Any, 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, Any, Not = Rule.All, Rule.Any, Rule.Not
local Dash: AvatarAbilities.AbilityDefinition = {
Name = "Dash",
Input = { InputName = "Dash", Mode = "Press", ActionSlot = 5 }
}
  • InputName 是邏輯名稱,而不是鍵。CCL 生成一個輸入傳感器,並始終將其 AND 進入 StartsWhen。

  • Mode 定義此輸入如何啟動和停止能力。RunsWhile 從不包含輸入本身;它僅包含世界條件,例如在地面上或在水中,因此 Mode 是輸入驅動啟動和停止的唯一來源:

    模式啟動從輸入停止
    Press按下時。從不。能力通過衝突、自身的 RunsWhile 或調用 Stop() 自行結束。
    Hold按下時。釋放時。
    Hold 與 Repeats按下時。釋放結束重新觸發,而不是已經在飛行中的循環。
    Toggle切換開啟時。切換關閉時。

    Press 適合於像衝刺、攻擊和投擲這樣的離散行動。Hold 和 Toggle 適合於像衝刺、瞄準、阻擋、蹲下和懸浮這樣的持續行動。Hold 與 Repeats 適合於在持有時自我停止和重新觸發的行動,例如重複跳躍。

  • Repeats(布林值,僅限於 Hold)使能力在每個循環中自我終止,並在輸入保持按住時重新觸發,而不是在整個持有期間持續運行。

  • OutlivesInputWhile(僅限於 Hold/Toggle)是一個 條件,在該條件下能力在釋放或切換關閉後繼續運行,直到條件清除。當能力應在特定世界條件下超過其輸入時使用它。

  • ActionSlot 定義一個 動作槽,該槽與 輸入動作系統 中的一系列 InputActions 和 InputBindings 相關聯。

    幾個動作插槽輸入綁定是由 Roblox 預定義的,未來的 輸入動作管理器 將允許您根據需要重新配置動作插槽的默認輸入綁定。將 ActionSlot 設置為 0 將選擇下一個可用的空插槽。在移動設備上,插槽 1-7 會填充到屏幕上的按鈕(見下圖)。

    插槽鍵盤和滑鼠遊戲手把觸控默認分配
    1SpaceButtonA①跳躍
    2LeftShiftButtonL1②衝刺
    3LeftControlButtonB③蹲下
    4RButtonX④
    5MouseLeftButtonButtonR2⑤
    6QButtonY⑥
    7XButtonR1⑦
    8CButtonL2
    9FDPadLeft
    10GDPadRight
    11VDPadDown
  • CustomIcon、CustomIconActive 和 CustomIconInvalid 分別指定能力閒置、活動或不可用時的觸控按鈕的 Roblox 資產 ID。

RunsWhile 僅包含世界條件。編譯器根據 Mode 在幕後將輸入的效果組合到能力的實際延續中,因此將輸入本身放入 StartsWhen 或 RunsWhile 會引發錯誤(不要在那裡引用 Rule.Input)。Hold 和 Toggle 能力在釋放或切換關閉時已經默認停止,因此您不需要在 RunsWhile 中重複這一點:

local AvatarAbilities = require("@rbx/AvatarAbilities")
local Rule = AvatarAbilities.Rule
local Sensor = AvatarAbilities.Identifiers.Sensor
local All, Any, Not = Rule.All, Rule.Any, Rule.Not
local Glide: AvatarAbilities.AbilityDefinition = {
Name = "Glide",
Input = { InputName = "Glide", Mode = "Hold", ActionSlot = 6 },
StartsWhen = Not(Sensor.Ground),
RunsWhile = Not(Sensor.Ground),
}

要使 Hold 或 Toggle 能力在世界條件下超過其輸入,請設置 OutlivesInputWhile,而不是將輸入添加到 RunsWhile。以下 Crouching 能力在玩家釋放蹲下輸入後保持蹲下,只要上方仍有物體:

local AvatarAbilities = require("@rbx/AvatarAbilities")
local Identifiers = AvatarAbilities.Identifiers
local Sensor = Identifiers.Sensor
local Crouching: AvatarAbilities.AbilityDefinition = {
Name = "Crouching",
Input = { InputName = "Crouch", Mode = "Hold", OutlivesInputWhile = Sensor.Ceiling, ActionSlot = 3 },
RunsWhile = Sensor.Ground,
}

傳感器

傳感器 是有關世界的命名值,引擎為您讀取。您通常會讀取傳感器而不是寫入它們。為了方便起見,幾個傳感器已經預先註冊:

傳感器描述
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.AbilityOwner — 角色的 Model,使得 managerCtx.AbilityOwner.PrimaryPart 是根部件。
  • managerCtx.AbilityManager — 管理器的簡化視圖,以便能力可以在其自己的回調中添加、移除和查詢能力。
  • managerCtx.BodyParts — 角色的身體部件,具有每個肢體開啟和關閉碰撞的幫助器。
  • managerCtx.ControllerManager — 角色的 ControllerManager 用於物理控制。當沒有註冊的能力需要物理時,它可以是 nil。
  • 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 是錯誤的。

©2026 Roblox Corporation、Roblox、Roblox 標誌及 Powering Imagination 是我們在美國及其他國家地區的部分註冊與未註冊商標。