De Karaktercontrollerbibliotheek (CCL) is een modulair framework voor het bouwen van karakterbeweging en -gedrag via attributen en Luau-scripts. Deze architectuur vervangt rigide Humanoid toestandsmachines door een flexibel, uitbreidbaar systeem voor karaktermechanica.
CCL inschakelen
De CCL is opt-in via het venster Avatar-instellingen in Studio. Om het in te schakelen:
Schakel de CCL-bèta in via Bestand ⟩ Bèta-functies ⟩ AvatarAbilities Character Controller Library.
Ga naar het tabblad Avatar en open Avatar-instellingen.

Selecteer het tabblad Beweging aan de linkerkant van het venster en selecteer in de sectie Vaardigheden Character Controller Library.

Alle standaardvaardigheden zoals Rennen, Springen en Klimmen zijn standaard ingeschakeld. Om een van deze tijdens runtime uit te schakelen, vink je het bijbehorende vakje uit.
Vaardigheden
Vaardigheden evalueren wat een karakter kan doen, zoals de mogelijkheid om te rennen, springen, klimmen en zwemmen. In plaats van te vertrouwen op een vaste set van door de engine gedefinieerde karaktertoestanden zoals die in Enum.HumanoidStateType, bepalen CCL-vaardigheden dynamisch wat een karakter kan doen en hoe het moet reageren op spelersinvoer.
Structueel is een vaardigheid een zelfbevatte Luau-tabel die voornamelijk het volgende specificeert:
| Tabelvelden | Doel |
|---|---|
| Naam | De unieke identiteit van de vaardigheid; voorwaarden en conflicten verwijzen ernaar bij naam. Het registreren van twee vaardigheden met dezelfde Naam genereert een fout. Voor een paar vergelijkbare vaardigheden, geef elke een andere Naam en deel een gemeenschappelijk label in Labels. De naam van de ModuleScript bepaalt de unieke configuratiesleutel. |
| Labels, TimedLabels | Genomineerde bits in een gedeelde 64-bits masker die fungeert als de coördinatiebus tussen vaardigheden; zie labels. |
| StartsWhen, RunsWhile | Voorwaarden die definiëren wanneer de vaardigheid moet starten en wanneer deze actief moet blijven; zie voorwaarden. |
| Blocks, Stops, Suspends, ExclusiveGroup | Hoe om te gaan met conflicten tussen vaardigheden die niet tegelijkertijd actief kunnen zijn. |
| Input | De invoer die de vaardigheid activeert. Input.Mode controleert hoe de invoer de vaardigheid start en stopt; RunsWhile bevat alleen wereldvoorwaarden, nooit de invoer zelf; zie invoeren. |
| Config, State | Standaardconfiguratiewaarden en gerepliceerde status voor elke vaardigheidsregistratie. Callbacks lezen configuratie van abilityCtx.Config en lezen of schrijven gerepliceerde status via abilityCtx.State. |
| OnSetup, OnStart, OnStop, OnUpdate, OnTeardown | Levenscycluscallbacks waar het daadwerkelijke gedrag van de vaardigheid wordt gescript; zie callbacks. |
Labels
Een label is een genomineerde bit in een gedeelde 64-bits masker die fungeert als de coördinatiebus tussen vaardigheden. Essentieel:
- Een actieve vaardigheid zendt zijn Labels en TimedLabels uit naar het wereldmasker.
- Vaardigheid conflicten definiëren welke andere vaardigheden worden geblokkeerd, gestopt of opgeschort bij activatie.
In de volgende opstelling wordt het label "CanFallDown" uitgezonden naar het wereldmasker wanneer Running actief is. De FallingDown vaardigheid met zijn voorwaarde van StartsWhen = All( "CanFallDown", "Stunned" ) wordt automatisch een kandidaat, maar "Stunned" moet ook naar het wereldmasker worden uitgezonden voordat FallingDown plaatsvindt.
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" }, -- Labels worden uitgezonden wanneer de vaardigheid actief is
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, Any, Not = Rule.All, Rule.Any, Rule.Not
local FallingDown: AvatarAbilities.AbilityDefinition = {
Name = Ability.FallingDown,
StartsWhen = All( "CanFallDown", "Stunned" ), -- Labels die nodig zijn voor de vaardigheid om te starten
Blocks = { Ability.Running }
}Labels kunnen ook op een getimede manier worden uitgezonden of geconsumeerd met behulp van de TimedLabels woordenboek.
| Sleutel | Beschrijving |
|---|---|
| TimedLabels.OnStart | Woordenboek met labels (sleutels) en bijbehorende duur. Label(s) worden uitgezonden wanneer de vaardigheid begint en vervallen automatisch wanneer hun duur eindigt. Bijvoorbeeld, OnStart = { Dashing = 1 } zendt het Dashing label uit voor 1 seconde wanneer de vaardigheid begint. |
| TimedLabels.OnStop | Woordenboek met labels (sleutels) en bijbehorende duur. Label(s) worden uitgezonden wanneer de vaardigheid stopt en vervallen automatisch wanneer hun duur eindigt. Bijvoorbeeld, OnStop = { DashCooldown = 2 } zendt het DashCooldown label uit voor 2 seconden wanneer de vaardigheid stopt. |
| TimedLabels.Consumes | Lijst van labels om te verwijderen (consumeren) wanneer de vaardigheid activeert. Bijvoorbeeld, als een vechtspel spelers toestaat om tegenaanvallen uit te voeren na het blokkeren van een aanval van een tegenstander, kan de CounterAttack vaardigheid zowel StartsWhen = "AfterBlock" als TimedLabels = { Consumes = { "AfterBlock" } } bevatten om dubbele activering van de CounterAttack vaardigheid te voorkomen. |
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 },
},
}Voorwaarden
Een voorwaarde is een of meer labels, sensoren, of een invoerverwijzing, gebruikt door StartsWhen en RunsWhile. Voorwaarden compileren tot bitmaskeroperaties tijdens runtime en evaluatie is gehele getallen wiskunde — geen tabelwandelingen en geen stringvergelijkingen.
| Doel | Syntax | Voorbeeld |
|---|---|---|
| Één vereiste voorwaarde. | StartsWhen = Sensor.Ground | |
| EN logica voor wanneer alle labels bestaan in het wereldmasker en alle sensoren actief zijn. | All() | StartsWhen = All( "CanFallDown", "Stunned" ) |
| OF logica voor wanneer een van de labels bestaat in het wereldmasker of een van de sensoren actief is. | Any() | StartsWhen = Any( "WallClimbing", "Climbing" ) |
| Negatie zodat de labels niet kunnen bestaan in het wereldmasker en de sensoren niet actief kunnen zijn. | Not() | RunsWhile = Not("Stunned") |
Voorwaardelijke evaluatie kan worden gecombineerd voor complexere logica, zoals All() chaining plus Not() om aan te geven dat een sensor actief moet zijn terwijl een label niet mag bestaan:
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") ),
}Conflicten
Sommige vaardigheden kunnen niet actief zijn wanneer een andere vaardigheid actief is; bijvoorbeeld, karakters kunnen niet springen terwijl ze zwemmen, en ze kunnen niet rennen terwijl ze vallen. De engine lost deze conflicten declaratief op binnen de definitie van een vaardigheid:
| Conflict Sleutel | Doel |
|---|---|
| Blocks | Terwijl de bezittende vaardigheid actief is, kunnen de vermelde andere vaardigheden niet starten. Bijvoorbeeld, een ScopeAim vaardigheid kan Blocks = { Ability.Running, Ability.Jumping } bevatten om te voorkomen dat karakters rennen of springen terwijl ze zorgvuldig door de scope van hun wapen richten. |
| Stops | Wanneer de bezittende vaardigheid start, worden de vermelde andere vaardigheden gedwongen gestopt en moeten opnieuw worden geactiveerd. Bijvoorbeeld, een Hover vaardigheid kan Stops = { Ability.Running } bevatten om onmiddellijk de loopbeweging van een karakter te stoppen wanneer ze beginnen te zweven. |
| Suspends | Wanneer de bezittende vaardigheid start, pauzeren de vermelde andere vaardigheden en herstarten automatisch wanneer de bezittende vaardigheid stopt. Bijvoorbeeld, een aangepaste sprintvaardigheid kan Suspends = { Ability.Running } bevatten zodat rennen 🄐 pauzeert bij het starten van de sprint, 🄑 wordt geblokkeerd tijdens de sprint, en 🄒 herstart bij het stoppen van de sprint. |
Een unieke conflict sleutel is ExclusiveGroup die meerdere vaardigheden in een groep plaatst, elk met een Priority waarde. Slechts één vaardigheid per groep kan actief zijn en hogere prioriteit wint. Echter, als een uitdager Stops verklaart die gericht is op de naam/label van de houder, wint deze ongeacht de prioriteit.
In de volgende opstelling worden drie vaardigheden (Sprinting, Crouching, Stagger) toegevoegd aan een Locomotion exclusieve groep. Sprinting heeft de hoogste prioriteit (200) zodat het wint van Crouching (100) en de twee nooit tegelijkertijd draaien. Echter, Stagger stopt gedwongen de sprint (Stops = { Ability.Sprinting }), zodat het Sprinting kan onderbreken en supersede, ook al is de prioriteit (150) lager.
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 },
}
-- Een vaardigheid met lagere prioriteit kan een vaardigheid met hogere prioriteit overschrijven door deze te stoppen
local Stagger: AvatarAbilities.AbilityDefinition = {
Name = "Stagger",
ExclusiveGroup = { Name = "Locomotion", Priority = 150 },
Stops = { Ability.Sprinting },
}Invoeren
De Input definitie van een vaardigheid specificeert de invoer die wordt gebruikt om te proberen de vaardigheid te activeren. Het neemt sleutel-waarde paren die het invoergedrag, de actielocatie en optionele aanraakknopiconen configureren.
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 is een logische naam, geen sleutel. De CCL genereert een invoersensor en AND't deze altijd in StartsWhen.
Mode definieert hoe deze invoer de vaardigheid start en stopt. RunsWhile bevat nooit de invoer zelf; het bevat alleen wereldvoorwaarden, zoals op de grond zijn of in water, zodat Mode de enige bron is van invoergestuurde start en stop:
Mode Start Stop Van Invoer Press Bij indrukken. Nooit. De vaardigheid beëindigt zichzelf via een conflict, zijn eigen RunsWhile, of door Stop() aan te roepen. Hold Bij indrukken. Bij loslaten. Hold met Repeats Bij indrukken. Loslaten beëindigt de heractivatie, niet de cyclus die al in de lucht is. Toggle Bij inschakelen. Bij uitschakelen. Press is geschikt voor discrete acties zoals dash, aanvallen en gooien. Hold en Toggle zijn geschikt voor aanhoudende acties zoals sprinten, richten, blokkeren, hurken en zweven. Hold met Repeats is geschikt voor acties die zichzelf stoppen en opnieuw activeren terwijl ze worden vastgehouden, zoals herhaald springen.
Repeats (boolean, alleen Hold) maakt de vaardigheid zelf-terminerend bij elke cyclus en heractiveert terwijl de invoer vastgehouden blijft, in plaats van continu te draaien voor de hele houdperiode.
OutlivesInputWhile (Hold/Toggle alleen) is een voorwaarde waaronder de vaardigheid blijft draaien na loslaten of uitschakelen, en stopt zodra de voorwaarde is opgeheven. Gebruik het wanneer een vaardigheid langer moet duren dan zijn invoer onder een specifieke wereldvoorwaarde.
ActionSlot definieert een actielocatie die is gekoppeld aan een lijst van InputActions en InputBindings binnen het Input Action System.
Verschillende actie slot invoerbindingen zijn vooraf gedefinieerd door Roblox en, in de toekomst, zal de Input Action Manager je in staat stellen om standaard invoerbindingen voor actie slots naar wens opnieuw te configureren. Het instellen van ActionSlot op 0 kiest de volgende beschikbare lege slot. Op mobiele apparaten vullen slots 1-7 zich met knoppen op het scherm (zie diagram hieronder).
Slot Toetsenbord & Muis Gamepad Touch Standaard Toewijzing 1 Space ButtonA ① Springen 2 LeftShift ButtonL1 ② Rennen 3 LeftControl ButtonB ③ Hurken 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, en CustomIconInvalid specificeren Roblox asset-ID's voor de aanraakknop wanneer de vaardigheid inactief, actief of niet beschikbaar is.
RunsWhile bevat alleen wereldvoorwaarden. De compiler stelt het effect van de invoer samen in de daadwerkelijke voortzetting van de vaardigheid achter de schermen op basis van Mode, dus het invoeren zelf in StartsWhen of RunsWhile genereert een fout (verwijs daar niet naar Rule.Input). Hold en Toggle vaardigheden stoppen al bij loslaten of uitschakelen als standaard, dus je hoeft dat niet te dupliceren in 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),
}Om een Hold of Toggle vaardigheid langer te laten duren dan zijn invoer onder een wereldvoorwaarde, stel je OutlivesInputWhile in in plaats van de invoer toe te voegen aan RunsWhile. De volgende Crouching vaardigheid blijft hurken nadat de speler de hurkinvoer loslaat, zolang er iets boven blijft:
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,
}Sensoren
Een sensor is een genomineerde waarde over de wereld die de engine voor je leest. Je leest meestal sensoren in plaats van ze te schrijven. Voor het gemak zijn verschillende sensoren vooraf geregistreerd:
| Sensor | Beschrijving |
|---|---|
| Sensor.Ground | Staan op een oppervlak |
| Sensor.IsMoving | Bewegingsinvoer wordt toegepast |
| Sensor.MoveInput | De bewegingsvector zelf |
| Sensor.Ceiling | Iets is direct boven je |
| Sensor.Climb | Een klimoppervlak is binnen bereik |
| Sensor.Water / Sensor.WaterSurface | In water / aan het oppervlak |
| Sensor.Sit | Zittend |
| Sensor.Tipped | Omgevallen |
| Sensor.Tool | Een Tool vasthouden |
| Sensor.LookDirectionInput | De opgegeven kijkrichting |
| Sensor.RotateToLookDirectionInput | Of het karakter moet draaien naar de opgegeven kijkrichting |
Callbacks
Vaardigheid callback-functies stellen je in staat om specifiek gedrag te scripten:
Hoewel je aangepaste vaardigheden op de server registreert, worden hun callbacks uitgevoerd in zowel de voorspelde client-simulatie als de autoritatieve server-simulatie. Houd het callback-gedrag deterministisch zodat beide simulaties hetzelfde resultaat opleveren.
| Callback | Voert uit | Gebruikscases |
|---|---|---|
| OnSetup(managerCtx, abilityCtx) | Eén keer, wanneer de vaardigheid wordt geregistreerd. | Referenties cachen, status initialiseren, enz. |
| OnStart(managerCtx, abilityCtx, hadLabel) | Elke keer dat de vaardigheid wordt geactiveerd. | Een effect toepassen zoals een impuls. De hadLabel() functie rapporteert of een specifiek label aanwezig was toen de activatie begon, vóór de conflictoplossing. |
| OnUpdate(managerCtx, abilityCtx) | Elke actieve frame. | Continue werkzaamheden zoals timers of per-frame krachten. |
| OnStop(managerCtx, abilityCtx) | Elke deactivatie, vrijwillig of gedwongen. | Wat OnStart() deed ongedaan maken. |
| OnTeardown(managerCtx, abilityCtx) | Bij het verwijderen van de vaardigheid. | Verbindingen ontkoppelen, instanties vernietigen, enz. |
Elke callback-functie heeft als eerste parameter managerCtx, een ManagerContext object met gedeelde karakter- en manager-eigenschappen, waaronder:
- managerCtx.AbilityOwner — Het karakter Model zodat managerCtx.AbilityOwner.PrimaryPart het wortelonderdeel is.
- managerCtx.AbilityManager — Een verkorte weergave van de manager zodat een vaardigheid vaardigheden kan toevoegen, verwijderen en opvragen vanuit zijn eigen callbacks.
- managerCtx.BodyParts — De lichaamsdelen van het karakter, met helpers voor het in- en uitschakelen van botsingen per ledemaat.
- managerCtx.ControllerManager — De ControllerManager van het karakter voor fysica-controle. Het kan nil zijn wanneer geen geregistreerde vaardigheid fysica vereist.
- managerCtx.RootCFrame — De CFrame van het wortelonderdeel, eenmaal vastgelegd aan het begin van het frame zodat callbacks het niet zelf hoeven op te halen.
- managerCtx.RootLookVector — Richting waarin het wortelonderdeel van het karakter kijkt.
- managerCtx.RootUpVectorY — De Y component van de opwaartse vector van het wortelonderdeel.
- managerCtx.TaskSynchronize() — Synchroniseert een callback vóór toegang tot het DataModel wanneer parallelle callback-ondersteuning is ingeschakeld. Momenteel wordt OnUpdate niet uitgevoerd in een parallelle context, dus deze functie heeft geen effect. Volledige Parallel Luau-ondersteuning is gepland voor een toekomstige update.
De tweede parameter, abilityCtx, is een AbilityContext object met door de engine beheerde tabellen voor de huidige vaardigheidsregistratie:
- abilityCtx.Config — Alleen-lezen configuratiewaarden voor deze vaardigheidsregistratie.
- abilityCtx.State — Veranderlijke status die door het DataModel wordt gerepliceerd. Server Authority herstelt deze waarden tijdens terugrol en hersimulatie.
- abilityCtx.Local — Veranderlijke tijdelijke status die niet gerepliceerd wordt of deelneemt aan terugrol.
Bewaar aangepaste callback-gegevens in abilityCtx.State of abilityCtx.Local. Het rechtstreeks schrijven van aangepaste velden naar abilityCtx is een fout.