§ How to · with Picoo
How to animate in Roblox Studio (and what code cannot do)
By Sametcan Tasgiran, Founder & Developer·Published ·Updated
No script can create a Roblox keyframe animation. Every tool that claims otherwise is producing an asset ID that does not exist.
Animation in Roblox splits cleanly in two: authored clips (Animation Editor → uploaded asset → played by ID) and procedural motion (CFrame and Motor6D, written in code). Knowing which one you need is most of the problem.
Idle sway and a swing
By default the script adds a slow sway to the arms and a small bob to the body every frame, plus a one-shot swing you trigger with _G.Anim.swing(). No upload and no asset ID.
Recoil and landing dip
Ask for them and the same script adds _G.Anim.recoil(amount) and a dip that plays by itself when the character lands.
Poses from a cached C0
Each Motor6D's original C0 is cached and every pose is that base times an offset, so limbs never drift. The joints are cached again after every respawn.
Plays an animation you own
Give Picoo the ID of an animation you own and the script adds _G.Anim.playAsset(), which loads it through the Humanoid's Animator and plays it. Without an ID it leaves a commented template and invents nothing.
R6 joint names
Poses target the R6 joints Right Shoulder, Left Shoulder, RootJoint and Neck. On an R15 rig the shoulders are named RightShoulder and LeftShoulder, so ask for R15 joint names in a follow-up prompt.
Files Picoo ships for this prompt
1 file · 112 lines · one recipe call
StarterPlayer.StarterPlayerScripts.ProceduralAnimation
LocalScript that caches the character's Motor6D joints, caches them again on respawn, and poses the idle sway and the swing on RenderStepped. Exposes _G.Anim.
112 lines
Sample output: StarterPlayer.StarterPlayerScripts.ProceduralAnimation
RunService.RenderStepped:Connect(function(dt)
local t = os.clock()
-- Idle sway: a slow figure-of-eight on the arms so a standing character is
-- not perfectly still. Small amplitude on purpose -- readable, not seasick.
local sway = math.sin(t * 1.6) * SWAY
local bob = math.sin(t * 3.2) * SWAY * 0.4
pose("Right Shoulder", CFrame.Angles(sway, 0, 0))
pose("Left Shoulder", CFrame.Angles(-sway, 0, 0))
pose("RootJoint", CFrame.new(0, bob * 0.3, 0))
if swingT >= 0 then
swingT += dt
local a = math.clamp(swingT / SWING_TIME, 0, 1)
-- Fast out, slow back: a linear arc reads as robotic.
local curve = math.sin(a * math.pi)
pose("Right Shoulder", CFrame.Angles(-curve * 2.2, 0, -curve * 0.5))
if a >= 1 then swingT = -1 end
end
end)
--------------------------------------------------------------------
-- Playing a REAL animation asset
--------------------------------------------------------------------
-- To play a keyframe animation you must supply an ID of an animation YOU own:
--
-- local animation = Instance.new("Animation")
-- animation.AnimationId = "rbxassetid://YOUR_ID_HERE"
-- local track = humanoid:FindFirstChildOfClass("Animator"):LoadAnimation(animation)
-- track:Play()
--
-- No ID was generated for you on purpose. An invented ID produces a track that
-- loads and plays nothing, with no error -- which is worse than no code at all.
_G.Anim = AnimHow to animate in Roblox Studio (and what code cannot do)
This is the one Roblox topic where the useful answer starts with a limit: a script cannot create a keyframe animation. Roblox animations are authored in the Animation Editor, uploaded to an account, and referenced by an asset ID that only exists because of that upload. There is no API that turns code into a clip.
That matters because it is a favourite failure of AI tools. Asked to "animate the sword swing", a model will happily write `animation.AnimationId = "rbxassetid://1234567890"` — a plausible-looking number that is either nothing or somebody else's animation. The code runs, nothing plays, and the developer spends an hour debugging a lie.
What code CAN do splits in two, and almost every real requirement lands in one of them.
Playing authored clips: load the Animation onto an Animator (not the Humanoid directly — that path is deprecated), keep a reference to the returned AnimationTrack, set a Priority that beats the default Animate script, and fade in and out rather than snapping. Most "my animation doesn't play" reports are one of those four things.
Procedural motion: CFrame and Motor6D driven per frame. This is where game feel actually lives, because it reacts to state — recoil that scales with the weapon, a swing arc that follows the mouse, hover that responds to speed, a door that opens as far as it was pushed. An authored clip is the same every time; procedural motion answers what is happening right now. It also needs no upload, no asset ownership and no moderation wait, which is why Picoo's combat_system recipe animates its swings, block and parry by tweening the shoulder joints.
Ask Picoo to "add an idle animation" or "add a swing animation when I attack" and its procedural_animation recipe writes one LocalScript in StarterPlayerScripts that works this way. It caches each joint's original C0, poses base times offset every frame, and caches the joints again after a respawn, because a respawn builds a new character. Given the ID of an animation you own, it also adds a function that plays it. It never makes an ID up.
The practical rule: if the motion is a fixed performance (a dance, a reload, a walk cycle) author it in the Animation Editor. If it depends on anything the player is doing, write it.
See more on the Luau generator, the AI Luau script writer, the 3D model generator and the game builder, read how Picoo compares with ChatGPT, or browse the full blog.
Frequently asked
Can AI write a Roblox animation for me?+
It can write the code that PLAYS one, and it can write procedural motion. It cannot author a keyframe clip: Roblox animations are created in the Animation Editor and uploaded to your account, which produces an asset ID tied to that upload. Any tool that hands you an AnimationId it "generated" has invented a number — it will either fail to load or load somebody else's animation.
Why does my animation not play?+
Three usual causes. The asset is not owned by (or shared with) the place's creator, so it fails to load. The Priority is too low and the default Animate script overrides it — Action beats Movement beats Idle beats Core. Or the track is garbage-collected because you did not keep a reference to it.
When should I use procedural motion instead?+
Whenever the motion depends on runtime state: recoil scaled by weapon, a swing that follows the mouse, hover that responds to speed, a door that opens as far as the player pushed it. Authored clips are fixed; procedural motion reacts. Most "game feel" is procedural.
What is Motor6D and why does it matter?+
It is the joint that connects two parts of a rig — the character's shoulders, neck, hips. Rotating a Motor6D's C0 moves that limb without touching the animation system at all, which is how aim offsets and head-look are done while a walk animation is still playing.
Do I need an Animator object?+
Yes, on modern Roblox. LoadAnimation on the Humanoid directly is deprecated; get or create an Animator inside the Humanoid (or an AnimationController for non-humanoid rigs) and load through that.
Related Picoo prompts
Roblox combat system
3 scripts · 1,181 lines · one recipe call. Press Play and fight with M1, E, F, Q, R and Shift.
Roblox pathfinding NPC
Example build: 5 files · 156 lines. Picoo writes this code for each prompt, so file names and line counts vary from run to run.
an ability system with cooldowns in Roblox
If the cooldown lives on the client, it is a suggestion. Every cooldown, cost and damage number here is enforced on the server.