How to Animate an NPC in Roblox: Idle, Walk and Custom Animations (2026)
Make a Roblox NPC idle, walk and react with copy-paste scripts: set up the rig, get an animation ID, play it through the Animator, switch idle and walk with pathfinding, and fix the usual reasons it will not play.
“A person sprints forward naturally with fast steps and swinging arms. Loop naturally”
- An NPC animates the same way a player does: an Animation with an asset ID, loaded through the Animator inside its Humanoid, then played as a track.
- Do it from a server Script inside the NPC. A LocalScript in the Workspace never runs, and an NPC’s animations only replicate when the server plays them.
- Use
Animator:LoadAnimation(). The olderHumanoid:LoadAnimation()is deprecated. - Most “it won’t play” bugs are one of five things: anchored limbs, a missing permission, a low priority, the wrong rig type, or a LocalScript.
- Need the animations themselves? Generate idles, walks and gestures on R15 from a sentence with NPCMotion, then use the scripts below.
On this page
- 01How do you set up an NPC rig?
- 02Where do you get the animation?
- 03Why does my NPC animation only play for me?
- 04How do you play an animation on an NPC?
- 05How do you make an NPC walk with a walk animation?
- 06How do you play an animation when a player walks up?
- 07What do animation priorities do?
- 08Should NPC animations run on the server or the client?
- 09Why won’t my NPC animation play?
- 10How do you make lots of NPC animations quickly?
To animate an NPC in Roblox, give it an Animator, load an animation by its asset ID from a server Script, and play the track. That is four lines once the rig is set up. The rest of this guide covers everything around those four lines: where the animation comes from, why it might only play for you, how to switch between idle and walk as the NPC moves, and how to make it react when a player walks up.
How do you set up an NPC rig?
- 1Insert a rig. In Studio, open the Character menu on the Avatar or Home tab (the Rig Generator) and choose R15. You get a model with a
Humanoid, aHumanoidRootPartand fifteen body parts joined by Motor6Ds. - 2Name it and move it into place. Rename the model to something like “Shopkeeper”. Folders such as
Workspace.NPCskeep larger games manageable. - 3Check nothing is anchored except, optionally, the root. Animations move limbs through their Motor6Ds, and an anchored limb cannot move. For an NPC that should never leave its spot, anchoring only the
HumanoidRootPartis fine. - 4Make sure it has an Animator. Look inside the Humanoid. If there is no
Animator, the scripts below create one on the server, which is where it must be created for animations to replicate.
| Your NPC is… | Use | Animations from |
|---|---|---|
| A person, using the standard avatar shape | Humanoid with an Animator (R15) | R15 animations, including generated ones |
| A person on an old R6 rig | Humanoid with an Animator (R6) | R6 animations only; R15 clips will not fit |
| A creature, vehicle or prop | AnimationController with an Animator | Animations keyed on that exact rig |
Where do you get the animation?
You need an animation asset ID: the number in rbxassetid://123456789. There are three ways to make the animation behind it.
| Route | How | Good for |
|---|---|---|
| Animation Editor | Pose the rig keyframe by keyframe in Studio | Exact, stylised moves and anything holding props |
| Animation Capture (beta) | Upload a video under 15 seconds of one person, in the Animation Editor | Quick body motion you can act out |
| NPCMotion | Type the move or upload a phone clip; get an R15 KeyframeSequence with the feet locked | Idles, walks, jobs, gestures and reactions in bulk |
Whichever you use, finish in the Animation Editor: open the animation on your NPC, check it, then use Publish to Roblox and copy the ID it gives you. Publish it under the same creator as the game, which for a group game means choosing the group.
Why does my NPC animation only play for me?
Usually permissions. Since July 2025, an experience needs permission to load an animation asset. Your own animations are always available in your own games, and playtesting in Studio grants permission automatically. Problems start when the animation and the game have different owners.
- Group game, personal animation. Publish the animation under the group instead, or grant the experience access from the animation’s Permissions page on the Creator Hub.
- Someone else’s animation. Animations cannot be set to open use. Ask the owner to grant your experience access, or make your own.
- It worked yesterday. Check the Output window for a permission or asset failure on the ID. A failed load is reported there even when nothing else looks wrong.
How do you play an animation on an NPC?
Put a Script (not a LocalScript) inside the NPC model and replace the ID with yours. This loops an idle forever, which is all a shopkeeper or a guard needs:
-- Script (not LocalScript) inside the NPC model
local npc = script.Parent
local humanoid = npc:WaitForChild("Humanoid")
-- Use the NPC's Animator, creating one on the server if it has none
local animator = humanoid:FindFirstChildOfClass("Animator")
if not animator then
animator = Instance.new("Animator")
animator.Parent = humanoid
end
local idleAnimation = Instance.new("Animation")
idleAnimation.AnimationId = "rbxassetid://YOUR_IDLE_ID"
local idleTrack = animator:LoadAnimation(idleAnimation)
idleTrack.Priority = Enum.AnimationPriority.Idle
idleTrack.Looped = true
idleTrack:Play()Two details matter. Load each animation once and keep the track: every LoadAnimation call makes a new track, and loading in a loop leaks them. And set Looped in the script rather than trusting the setting the animation was published with, so the behaviour is visible in the code.
How do you make an NPC walk with a walk animation?
Players get walking for free from the Animate script in their character. That script is a LocalScript built for players, so an NPC you move with Humanoid:MoveTo() slides along in its idle pose. The fix is a small controller that listens to the Humanoid’s Running event and switches tracks, plus pathfinding so it walks around walls.
-- Script inside the NPC model. Walks to a part named Target,
-- playing walk while moving and idle while standing.
local PathfindingService = game:GetService("PathfindingService")
local npc = script.Parent
local humanoid = npc:WaitForChild("Humanoid")
local root = npc:WaitForChild("HumanoidRootPart")
root:SetNetworkOwner(nil) -- the server simulates the NPC: no hand-off stutter
local animator = humanoid:FindFirstChildOfClass("Animator")
if not animator then
animator = Instance.new("Animator")
animator.Parent = humanoid
end
local function load(id, priority)
local animation = Instance.new("Animation")
animation.AnimationId = id
local track = animator:LoadAnimation(animation)
track.Priority = priority
track.Looped = true
return track
end
-- Your own clips, or Roblox's default R15 idle and walk
local idle = load("rbxassetid://507766666", Enum.AnimationPriority.Idle)
local walk = load("rbxassetid://507777826", Enum.AnimationPriority.Movement)
idle:Play()
-- Running fires with the NPC's speed, and with 0 when it stops
humanoid.Running:Connect(function(speed)
if speed > 0.5 then
if not walk.IsPlaying then
walk:Play(0.2)
idle:Stop(0.2)
end
walk:AdjustSpeed(speed / 16) -- keep feet in step at other WalkSpeeds
elseif walk.IsPlaying then
walk:Stop(0.2)
idle:Play(0.2)
end
end)
local function walkTo(goal)
local path = PathfindingService:CreatePath({ AgentRadius = 2, AgentHeight = 5, AgentCanJump = true })
local ok = pcall(function()
path:ComputeAsync(root.Position, goal)
end)
if not ok or path.Status ~= Enum.PathStatus.Success then
return false
end
for _, waypoint in path:GetWaypoints() do
if waypoint.Action == Enum.PathWaypointAction.Jump then
humanoid.Jump = true
end
humanoid:MoveTo(waypoint.Position)
-- MoveTo gives up after 8 seconds; false means it never arrived
if not humanoid.MoveToFinished:Wait() then
return false
end
end
return true
end
walkTo(workspace:WaitForChild("Target").Position)SetNetworkOwner(nil)keeps the NPC simulated on the server. Without it, physics ownership can pass to a nearby player and the walk stutters as it changes hands.AdjustSpeed(speed / 16)speeds the walk cycle up or down with the NPC’s actual speed, so feet do not slide when you changeWalkSpeed.MoveTotimes out after eight seconds. Walking waypoint by waypoint, as above, keeps each call short. For one longMoveTo, call it again before the eight seconds are up.- The two IDs are Roblox’s default R15 idle and walk. To double-check them, play solo, open your character’s Animate script and look at its idle and walk values.
“A person limps forward favoring the injured right leg with slow uneven steps”
A walk that tells a story: swap this in for the default walk ID and the same controller plays it, with no change to the script.
Default animations make every NPC move like every player. A tired farmer, a nervous thief and a proud knight should not share a walk. Swap the two IDs for your own and the same script gives each character its own personality.
How do you play an animation when a player walks up?
A ProximityPrompt is the simplest trigger: it shows a key prompt when a player is close and fires Triggered when they press it. Insert one into the NPC’s HumanoidRootPart, then add this Script to the NPC:
-- Script inside the NPC model. Add a ProximityPrompt to the
-- HumanoidRootPart, and put your wave animation's ID below.
local npc = script.Parent
local humanoid = npc:WaitForChild("Humanoid")
local root = npc:WaitForChild("HumanoidRootPart")
local prompt = root:WaitForChild("ProximityPrompt")
local animator = humanoid:FindFirstChildOfClass("Animator")
if not animator then
animator = Instance.new("Animator")
animator.Parent = humanoid
end
local waveAnimation = Instance.new("Animation")
waveAnimation.AnimationId = "rbxassetid://YOUR_WAVE_ID"
local wave = animator:LoadAnimation(waveAnimation) -- load once, play many times
wave.Priority = Enum.AnimationPriority.Action
wave.Looped = false
prompt.ActionText = "Talk"
prompt.Triggered:Connect(function(player)
local character = player.Character
local playerRoot = character and character:FindFirstChild("HumanoidRootPart")
if playerRoot then
-- Turn to face the player, staying upright
local target = Vector3.new(playerRoot.Position.X, root.Position.Y, playerRoot.Position.Z)
root.CFrame = CFrame.lookAt(root.Position, target)
end
if not wave.IsPlaying then
wave:Play()
end
end)The wave plays at Action priority, so it layers over the idle without stopping it, and when the wave ends the idle is still underneath. The same pattern drives a shopkeeper who nods when you buy something or a guard who raises a hand to stop you: one track per reaction, loaded once.
“Look scared then turn and run away with big dramatic strides”
A bigger reaction is still just another track: a villager who startles and runs from the player is loaded and played exactly like the wave.
What do animation priorities do?
When two tracks move the same joint, the higher priority wins. Getting this right is what lets an NPC wave while it idles, or swing a sword while it walks.
| Priority | Use it for | Notes |
|---|---|---|
| Core | Nothing of yours | The lowest. Roblox’s default animations play here, so anything you set higher overrides them |
| Idle | Standing, breathing, looking around | Loops underneath everything else |
| Movement | Walks, runs, climbs | Overrides idle while the NPC moves |
| Action | Waves, attacks, emotes, reactions | Plays over idle and movement |
| Action2 to Action4 | Something that must win over another action | Action4 is the highest priority there is |
Should NPC animations run on the server or the client?
On the server, for any NPC every player should see. Roblox only replicates animations on non-player rigs when the server loads and plays them, and the Animator itself must be created on the server.
Client-side playback is a deliberate optimisation for crowds that only need to look alive to one player, such as background pedestrians in a city. Each player then animates their own copy, and nobody sees anyone else’s.
Why won’t my NPC animation play?
| What you see | Likely cause | Fix |
|---|---|---|
| Nothing happens, no errors | The code is in a LocalScript in the Workspace, which never runs | Use a Script inside the NPC |
| Plays in Studio, not for others | The experience has no permission for the animation | Publish under the game’s owner, or grant access on the Creator Hub |
| Some limbs move, others are frozen | Those parts are anchored | Unanchor everything except, optionally, the HumanoidRootPart |
| The NPC snaps into a strange pose | An R6 animation on an R15 rig, or the reverse | Use an animation made for that rig type |
| It plays once and stops | Looped is false | Set track.Looped = true before playing |
| The wave never shows | Another track on the same joints has a higher priority | Raise the wave to Action, or lower the other track |
| It walks in its idle pose | NPCs have no Animate script | Use the walk controller above |
| The walk stutters near players | Physics ownership passing between server and players | root:SetNetworkOwner(nil) |
| A deprecation warning | Humanoid:LoadAnimation() | Load through the Animator instead |
How do you make lots of NPC animations quickly?
A living town needs dozens of clips: idles for every job, walks with personality, reactions to the player. Hand-keying each one is where most solo projects stall. Generating them takes that column off your plate.
- 1List every clip your NPCs need before you make any. The table in our 50 Roblox game ideas shows what a typical game needs.
- 2Generate them in NPCMotion by typing each move, or record yourself on a phone for anything with tricky timing. Foot contacts are locked and limbs are re-solved for R15.
- 3Bring them into Studio as a .rbxm or a pasted script, check each on its NPC in the Animation Editor, and publish.
- 4Paste the IDs into the scripts above.
Sources and further reading (checked Oct 6, 2026)
- Roblox Creator Hub, Use animations: create.roblox.com
- Roblox Engine API, Animator: create.roblox.com
- Roblox Engine API, AnimationPriority: create.roblox.com
- Roblox Engine API, Humanoid: create.roblox.com
- Roblox Creator Hub, Character pathfinding: create.roblox.com
- Roblox Creator Hub, Rig Generator: create.roblox.com
- Roblox Creator Hub, Animation Editor: create.roblox.com
- Roblox Creator Hub, Animation Capture: create.roblox.com
- Roblox DevForum, Improving animation asset permissions: devforum.roblox.com