§ How to · with Picoo
How to make a Roblox emote system (with AI)
By Sametcan Tasgiran, Founder & Developer·Published ·Updated
A Roblox emote system needs four pieces: a radial wheel UI, animation triggering, owned emote tracking, and unlock progression. Describe the emotes you want and Picoo writes the scripts for them. The build below is one example of that output.
Example build: 4 files · 130 lines. Picoo writes this code for each prompt, so file names and line counts vary from run to run. This one has an 8-slot wheel.
Radial wheel UI
Hold B to open the wheel, point the mouse at an emote, and release to play it. 8 slots in this example; the slot count is a setting.
Animation triggering
The server checks that the player owns the emote, then loads it on the character's Animator and plays it. Animations played on a character replicate, so every player sees it.
Owned emote tracking
Ownership is saved per player in a DataStore. Default emotes are free for everyone; premium ones unlock through whatever your game uses, such as a gamepass, a quest reward or a shop purchase.
Unlock progression
A new unlock shows a pop-up. Optional rarity tiers (common, rare, epic) color the glow around each emote icon.
Cooldown between emotes
After an emote, the player waits that emote's cooldown (2 seconds by default) before playing another. The wheel darkens while the cooldown runs.
Looping and one-shot emotes
Each emote is looping (a dance) or one-shot (a wave). In this example a looping emote stops when the player moves or uses another action.
Example output from a build like this
4 files in this example. Picoo writes this code for your prompt, so file names and sizes vary.
ServerScriptService/EmoteManager.lua
Ownership validation, animation dispatch
ReplicatedStorage/Modules/EmoteConfig.lua
Per-emote animation IDs, rarity, ownership rules
ReplicatedStorage/Remotes/PlayEmote
Client → server play request
StarterGui/EmoteWheel.lua
Radial wheel UI + selection
Sample output: ServerScriptService/EmoteManager.lua
--!strict
-- ServerScriptService/EmoteManager.lua (Picoo · excerpt)
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Config = require(ReplicatedStorage.Modules.EmoteConfig)
local PlayEmote = ReplicatedStorage:WaitForChild("Remotes"):WaitForChild("PlayEmote")
local lastPlayed: { [Player]: number } = {}
local owned: { [Player]: { [string]: boolean } } = {}
local function isOwned(player: Player, emoteId: string): boolean
local emote = Config[emoteId]
if not emote then return false end
if emote.default then return true end
return owned[player] and owned[player][emoteId] or false
end
PlayEmote.OnServerEvent:Connect(function(player: Player, emoteId: string)
local now = os.clock()
if (lastPlayed[player] or 0) > now then return end -- on cooldown
if not isOwned(player, emoteId) then return end
local emote = Config[emoteId]
local character = player.Character
if not character then return end
local humanoid = character:FindFirstChildOfClass("Humanoid")
if not humanoid then return end
local animator = humanoid:FindFirstChildOfClass("Animator")
if not animator then return end
local track = animator:LoadAnimation(emote.animation)
track.Looped = emote.looped or false
track:Play()
lastPlayed[player] = now + (emote.cooldown or 2)
end)Building a Roblox emote system
Emote systems are the social glue of social Roblox games. Players use emotes to greet friends, celebrate wins, and just have fun. A clean emote wheel makes the game feel modern; a chat-command-only system feels dated. Here is one example of what Picoo writes for it.
In this example Picoo wrote four files. EmoteConfig.lua holds per-emote definitions: animation, rarity, ownership rule, cooldown. EmoteManager.lua handles server-side validation and plays the animation. EmoteWheel.lua is the client UI that opens when B is held and selects emotes by mouse direction.
The radial wheel is the canonical pattern. Hold a key (B here), the wheel fades in at the center of the screen, mouse direction highlights a slot, and releasing the key plays the highlighted emote. Eight slots give variety without clutter; games built around emotes can raise the slot count.
Server-side ownership validation is the abuse prevention layer. The client sends a 'play emote X' request, and the server checks that the player owns it before playing the animation, so forged requests for premium emotes are ignored. Ownership is cached per session for fast repeat plays.
Cooldowns prevent emote spam. After an emote, the player waits 2 seconds by default before the next one: long enough to prevent visual chaos, short enough that normal social use feels responsive. The wheel darkens while the cooldown runs, so players know when their next emote is available.
Looping emotes such as dances stop when the player moves or uses another action, so a dance never gets in the way of play. Sounds, props and an emote shop are follow-up prompts on top of the same config.
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
How do I add a new emote?+
Add an entry to EmoteConfig.lua: id, displayName, animation (Animation instance), looped (bool), cooldown (seconds), rarity, default (bool — true for free-to-all). EmoteManager picks it up automatically.
Can emotes be locked behind gamepasses?+
Yes. Give the emote a gamepassId in EmoteConfig and have isOwned check it with MarketplaceService:UserOwnsGamePassAsync, caching the answer for the session. Ask for it in your prompt, with the pass ID.
How do I unlock an emote from a quest reward?+
Ask for a grant step, for example a BindableEvent that marks the emote as owned and saves it to the DataStore, and call it from your quest's completion code. EmoteManager is a server Script, so other scripts reach it through an event or a shared ModuleScript. Name your quest script in the follow-up prompt so the call goes in the right place.
What stops emote spam from being annoying?+
After any emote, the player waits that emote's cooldown before the next one: 2 seconds unless the emote sets its own. Give visually loud emotes a longer cooldown. The wheel shows the remaining time, so players know when they can play again.
Can I have emotes with sound?+
Yes. Ask for a soundId field in EmoteConfig and have EmoteManager play that sound from the character when the emote starts. It is a small follow-up prompt.
Related Picoo prompts
Roblox gamepass system
Example build: 4 files · 130 lines. Picoo writes this code for each prompt, so file names and line counts vary from run to run. Put your own pass IDs in the config before publishing.
Roblox shop system
8 files · 1,259 lines, 852 of them the shared PicooFeedback module · one recipe call. Three starter items by default; name your own items and prices in the prompt.
Roblox quest system
9 files · 1219 lines · one recipe call. 852 of those lines are PicooFeedback, the shared module behind the reward popups.