VluxyAI
Simple, composable AI for Roblox. An AI is a brain (a table of states), a pathfinder (plans), a mover (executes) and some senses (write a blackboard), stacked with the builder into an agent.
local VluxyAI = require(ReplicatedStorage.Packages.VluxyAI)
local agent = VluxyAI.new(model)
:UseBrain(Stalker)
:UsePathfinder(VluxyAI.Pathfinders.Navmesh.new({ AgentRadius = 2 }))
:UseMover(VluxyAI.Movers.Humanoid.new(model))
:AddSense(VluxyAI.Senses.Sight.new({ Range = 40 }))
:Build()
:Start()
Every part is a contract in Types; pass your own module in to extend the package.
Types
HumanoidPresetOptions
interface HumanoidPresetOptions {Navigation: NavigationOptions?--
Navigator tuning. Default { RepathInterval = 0.25, MaxPathAge = 2 }.
Graph: Pathfinder?--
Authored nodes (Graph): routes go over the graph first (Hybrid with Prefer = "Graph", RefineEnds = false) and the navmesh answers only where the graph has no way. Without it, the navmesh plans everything.
Doors: boolean?--
Walk through doors: Doors.Step with WalkThrough for "Door" steps, a Doors.Opener sense, and a direct walker that sees past unlocked doors. For doors rigs do not collide with (Collision.LetRigsThrough). Default false.
SafeWatch: boolean?--
Add SafeWatch, so the agent notices players in safe areas and is moved out of one that switches on around it (to a Graph node when given). Default true.
}PuppetPresetOptions
interface PuppetPresetOptions {Mover: CFrameMoverOptions?--
Options for [CFrameMover.new]: Speed, TurnSpeed, HeightOffset. HeightOffset defaults to 0 here, so the anchor's pivot is the floor point.
Navigation: NavigationOptions?--
Navigator tuning. Default { RepathInterval = 0.25, MaxPathAge = 2 }.
}HeadlessPresetOptions
interface HeadlessPresetOptions {Name: string?--
Used in messages. Default "Agent".
Yaw: number?--
Starting yaw in radians. Default 0.
Pathfinder: Pathfinder?--
Default a Navmesh built from Navmesh. A Graph or Straight keeps PathfindingService out of it.
Navigation: NavigationOptions?--
Navigator tuning. Default { RepathInterval = 0.25, MaxPathAge = 2 }.
}Properties
Utility
VluxyAI.Utility: UtilityUtility scoring: Utility.Best, Utility.Weighted, Utility.Curves.
When
VluxyAI.When: When
Ready-made When predicates for transitions and interrupts: When.Has, When.New,
When.Below, When.PathDone, When.Timer and the rest.
States
VluxyAI.States: StatesReady-made states: States.Patrol, States.Investigate, States.Search, States.Wander and States.Wait.
Cleaner
VluxyAI.Cleaner: CleanerThe package's cleanup bag, for anything you build around an agent.
Signal
VluxyAI.Signal: SignalPathfinders
The built-in Types.Pathfinders: Navmesh for geometry, Straight for a clear line, Ladder to try several in order, Graph for A* over authored nodes, and Hybrid to compose a graph with a local pathfinder.
Movers
The built-in Types.Movers. Record has no Instance at all, for headless agents.
Senses
The built-in Types.Senses. Hearing is for noises your code fires; Sounds is for the
tagged Sound instances the world is already playing; Awareness turns what the others
wrote into a detection meter; Neighbours is the group sense, so enemies sharing a map
know about each other and, when asked, keep out of each other's way.
Director
VluxyAI.Director: Director
Pacing and shared knowledge for a group of enemies: a tension meter, a difficulty knob and a
shared blackboard, read through director:Sense().
Interest
VluxyAI.Interest: Interest
Points of interest with a strength each, and Best to pick where an enemy looks next.
States.Roam walks one.
Claims
VluxyAI.Claims: ClaimsA shared "who is on what" table, so two enemies never chase the same player unless you say so.
Doors
VluxyAI.Doors: Doors
Doors agents open: :OnStep("Door", VluxyAI.Doors.Step()) over your door script, through
attributes or a driver of your own.
SafeAreas
VluxyAI.SafeAreas: SafeAreas
Parts tagged VLUXYAI_SAFE that agents never enter while VLUXYAI_SAFE/Enabled is not false. Call
VluxyAI.SafeAreas.Setup() once on the server.
Collision
VluxyAI.Collision: CollisionThe rig collision group, and parts agents walk through while players still collide with them.
PlayerNoise
VluxyAI.PlayerNoise: PlayerNoisePlayers make noise by moving: speed bands turned into noises on your Hearing signal.
Voice
VluxyAI.Voice: VoiceRandom voice lines by state, added as a sense: :AddSense(VluxyAI.Voice.new({ Lines = ... })).
Tables
VluxyAI.Tables: TablesThe package's small table helpers, including Tables.Prefixed.
Perception
VluxyAI.Perception: Perception
The helpers the built-in senses are made of: alive player roots, cones, line of sight, and
HumanoidOf for a state that acts on a target. The place to start for a custom sense.
Animator
VluxyAI.Animator: NPCAnimatorThe NPC animation helper.
Locomotion
VluxyAI.Locomotion: LocomotionIdle and walk for a rig from its real speed, plus one-shots by name, through the animator.
Footsteps
VluxyAI.Footsteps: FootstepsFootstep audio from measured movement, for the client's replica rigs (or a server rig).
Sync
Client-side presentation: a Broadcaster watches an agent on the server, a Replica drives a rig and your client states on the client. The game owns the remotes between them.
Combat
Attack.State, the one generic state, and Kill.Live and Kill.BlackBox, the two ways an agent kills a character.
Debug
Opt-in debug views, and a runtime R15 rig for tests and playgrounds.
Internals
The pieces the Agent is made of, for a custom scheduler or a client renderer that wants to run a brain table itself.
Presets
VluxyAI.Presets: {}
Ready-made stacks. Presets.Humanoid(model) returns a Builder already carrying a
Navmesh pathfinder (graph-first Hybrid when Graph is given) with Straight as its
direct walker, a HumanoidMover mover, Sight, Proximity and SafeWatch senses, and a
quarter-second repath; Doors = true adds walking through doors. Add a brain, any senses of
your own, and build. It is the stack the examples build by hand, opt-in and overridable.
local agent = VluxyAI.Presets.Humanoid(rig, { Graph = graph, Doors = true })
:UseBrain(Brain)
:AddSense(VluxyAI.Senses.Clues.new(interest))
:Build()
Presets.Puppet(anchor) is the server half of puppet mode, for an enemy with no visible body
on the server: a Navmesh pathfinder and a CFrameMover on the anchor (HeightOffset 0, so
its pivot is the floor point) with the same repath. A Part anchor is wrapped in a Model of its
own and made invisible, anchored and inert. It adds no senses; stream it with a Broadcaster
once built, and draw it on the client with a puppet Replica.
local agent = VluxyAI.Presets.Puppet(anchorPart, {
Navmesh = { AgentRadius = 4, AgentHeight = 12 },
Mover = { Speed = 10, TurnSpeed = 6 },
})
:UseBrain(Brain)
:AddSense(VluxyAI.Senses.Hearing.new(noises))
:Build()
local broadcaster = VluxyAI.Sync.Broadcaster.new(agent, { PositionRate = 10 })
Presets.Headless(options) is the same without any Instance on the server: a Record mover
holds the pivot, and the agent moves only when it is stepped. Start it with Start(true) and
step it from your own scheduler, or with Start() to tick on Heartbeat as usual.
local agent = VluxyAI.Presets.Headless({
Name = "Goblin 12",
Position = spawn,
Pathfinder = VluxyAI.Pathfinders.Graph.new(nodes),
Mover = { Speed = 10 },
})
:UseBrain(Brain)
:Build()
:Start(true)
Functions
new
Starts a Builder for entity. With no entity it builds a headless agent: give it a
Record mover, which holds the pivot instead.
NewAgent
Builds an Agent straight from a definition table, for code that assembles definitions itself rather than through the Builder.
Errors
| Type | Description |
|---|---|
| string | The definition failed validation; the message names the field. |
Validate
Checks a definition without building it. See Validate.
Errors
| Type | Description |
|---|---|
| string | The path and problem of the first bad field. |
ValidateBrain
Checks a brain table on its own. See Validate.Brain.
Errors
| Type | Description |
|---|---|
| string |