--// Universal Animation Logger GUI --// Put this LocalScript in StarterPlayerScripts or StarterGui --// Logs animation IDs from Self / NPCs / All --// Local-only logger local Players = game:GetService("Players") local UserInputService = game:GetService("UserInputService") local RunService = game:GetService("RunService") local player = Players.LocalPlayer --======================== -- EDIT HERE --======================== local guiTitle = "Animation Logger" local smallButtonText = "Open" local defaultScope = "All" -- "All", "Self", "NPCs" local maxLogRows = 200 --======================== local scopeModes = {"All", "Self", "NPCs"} local scopeIndex = 1 for i, mode in ipairs(scopeModes) do if mode == defaultScope then scopeIndex = i break end end local screenGui = Instance.new("ScreenGui") screenGui.Name = "AnimationLoggerGui" screenGui.ResetOnSpawn = false screenGui.IgnoreGuiInset = true screenGui.Parent = player:WaitForChild("PlayerGui") local mainFrame = Instance.new("Frame") mainFrame.Size = UDim2.new(0, 340, 0, 390) mainFrame.Position = UDim2.new(0.5, -170, 0.5, -195) mainFrame.BackgroundColor3 = Color3.fromRGB(25, 25, 25) mainFrame.BorderSizePixel = 0 mainFrame.Active = true mainFrame.ClipsDescendants = true mainFrame.Parent = screenGui local mainCorner = Instance.new("UICorner") mainCorner.CornerRadius = UDim.new(0, 12) mainCorner.Parent = mainFrame local titleBar = Instance.new("TextLabel") titleBar.Size = UDim2.new(1, 0, 0, 35) titleBar.BackgroundColor3 = Color3.fromRGB(35, 35, 35) titleBar.BorderSizePixel = 0 titleBar.Text = guiTitle titleBar.TextColor3 = Color3.fromRGB(255, 255, 255) titleBar.TextScaled = true titleBar.Font = Enum.Font.GothamBold titleBar.Active = true titleBar.Parent = mainFrame local titleCorner = Instance.new("UICorner") titleCorner.CornerRadius = UDim.new(0, 12) titleCorner.Parent = titleBar local hideButton = Instance.new("TextButton") hideButton.Size = UDim2.new(0, 60, 0, 25) hideButton.Position = UDim2.new(1, -65, 0, 5) hideButton.BackgroundColor3 = Color3.fromRGB(70, 70, 70) hideButton.Text = "Hide" hideButton.TextColor3 = Color3.fromRGB(255, 255, 255) hideButton.TextScaled = true hideButton.Font = Enum.Font.Gotham hideButton.BorderSizePixel = 0 hideButton.Parent = mainFrame local hideCorner = Instance.new("UICorner") hideCorner.CornerRadius = UDim.new(0, 8) hideCorner.Parent = hideButton local deleteButton = Instance.new("TextButton") deleteButton.Size = UDim2.new(0, 25, 0, 25) deleteButton.Position = UDim2.new(1, -30, 0, 5) deleteButton.BackgroundColor3 = Color3.fromRGB(170, 50, 50) deleteButton.Text = "X" deleteButton.TextColor3 = Color3.fromRGB(255, 255, 255) deleteButton.TextScaled = true deleteButton.Font = Enum.Font.GothamBold deleteButton.BorderSizePixel = 0 deleteButton.Parent = mainFrame local deleteCorner = Instance.new("UICorner") deleteCorner.CornerRadius = UDim.new(0, 8) deleteCorner.Parent = deleteButton local scrollFrame = Instance.new("ScrollingFrame") scrollFrame.Size = UDim2.new(1, 0, 1, -35) scrollFrame.Position = UDim2.new(0, 0, 0, 35) scrollFrame.BackgroundTransparency = 1 scrollFrame.BorderSizePixel = 0 scrollFrame.ScrollBarThickness = 5 scrollFrame.CanvasSize = UDim2.new(0, 0, 0, 0) scrollFrame.Parent = mainFrame local content = Instance.new("Frame") content.Size = UDim2.new(1, -10, 0, 0) content.Position = UDim2.new(0, 5, 0, 5) content.BackgroundTransparency = 1 content.BorderSizePixel = 0 content.Parent = scrollFrame local layout = Instance.new("UIListLayout") layout.Padding = UDim.new(0, 6) layout.SortOrder = Enum.SortOrder.LayoutOrder layout.Parent = content layout:GetPropertyChangedSignal("AbsoluteContentSize"):Connect(function() content.Size = UDim2.new(1, -10, 0, layout.AbsoluteContentSize.Y) scrollFrame.CanvasSize = UDim2.new(0, 0, 0, layout.AbsoluteContentSize.Y + 10) end) local function roundify(obj, radius) local c = Instance.new("UICorner") c.CornerRadius = UDim.new(0, radius) c.Parent = obj return c end local function makeLabel(text, height) local lbl = Instance.new("TextLabel") lbl.Size = UDim2.new(1, 0, 0, height or 22) lbl.BackgroundTransparency = 1 lbl.Text = text lbl.TextColor3 = Color3.fromRGB(255, 255, 255) lbl.TextScaled = true lbl.Font = Enum.Font.Gotham lbl.Parent = content return lbl end local function makeBox(labelText, defaultText) local row = Instance.new("Frame") row.Size = UDim2.new(1, 0, 0, 50) row.BackgroundColor3 = Color3.fromRGB(32, 32, 32) row.BorderSizePixel = 0 row.Parent = content roundify(row, 10) local lbl = Instance.new("TextLabel") lbl.Size = UDim2.new(1, -12, 0, 17) lbl.Position = UDim2.new(0, 6, 0, 3) lbl.BackgroundTransparency = 1 lbl.Text = labelText lbl.TextColor3 = Color3.fromRGB(255, 255, 255) lbl.TextScaled = true lbl.Font = Enum.Font.Gotham lbl.Parent = row local box = Instance.new("TextBox") box.Size = UDim2.new(1, -12, 0, 22) box.Position = UDim2.new(0, 6, 0, 24) box.BackgroundColor3 = Color3.fromRGB(45, 45, 45) box.Text = defaultText box.TextColor3 = Color3.fromRGB(255, 255, 255) box.TextScaled = true box.Font = Enum.Font.Gotham box.BorderSizePixel = 0 box.ClearTextOnFocus = false box.Parent = row roundify(box, 8) return box end local function makeButton(text, color, height) local btn = Instance.new("TextButton") btn.Size = UDim2.new(1, 0, 0, height or 30) btn.BackgroundColor3 = color btn.Text = text btn.TextColor3 = Color3.fromRGB(255, 255, 255) btn.TextScaled = true btn.Font = Enum.Font.GothamBold btn.BorderSizePixel = 0 btn.Parent = content roundify(btn, 10) return btn end makeLabel("Live animation logger", 22) local scopeButton = makeButton("Scope: " .. scopeModes[scopeIndex], Color3.fromRGB(80, 80, 140), 30) local refreshButton = makeButton("Refresh", Color3.fromRGB(80, 120, 80), 30) local copiedBox = makeBox("Copied ID", "") local statusLabel = makeLabel("Status: Ready", 22) local clearButton = makeButton("Clear Logs", Color3.fromRGB(120, 80, 40), 30) local logSectionTitle = makeLabel("Logs", 22) local smallButton = Instance.new("TextButton") smallButton.Size = UDim2.new(0, 70, 0, 30) smallButton.Position = UDim2.new(0, 10, 0.5, -15) smallButton.BackgroundColor3 = Color3.fromRGB(35, 35, 35) smallButton.Text = smallButtonText smallButton.TextColor3 = Color3.fromRGB(255, 255, 255) smallButton.TextScaled = true smallButton.Font = Enum.Font.GothamBold smallButton.BorderSizePixel = 0 smallButton.Visible = false smallButton.Active = true smallButton.Parent = screenGui local smallCorner = Instance.new("UICorner") smallCorner.CornerRadius = UDim.new(0, 10) smallCorner.Parent = smallButton local logsContainer = Instance.new("Frame") logsContainer.Size = UDim2.new(1, 0, 0, 0) logsContainer.BackgroundTransparency = 1 logsContainer.BorderSizePixel = 0 logsContainer.Parent = content local logsLayout = Instance.new("UIListLayout") logsLayout.Padding = UDim.new(0, 6) logsLayout.SortOrder = Enum.SortOrder.LayoutOrder logsLayout.Parent = logsContainer logsLayout:GetPropertyChangedSignal("AbsoluteContentSize"):Connect(function() logsContainer.Size = UDim2.new(1, 0, 0, logsLayout.AbsoluteContentSize.Y) end) local hookedAnimators = {} local logRows = {} local seenAnimationIds = {} local function updateStatus(text) statusLabel.Text = "Status: " .. text end local function trimText(s) return (tostring(s or ""):gsub("^%s+", ""):gsub("%s+$", "")) end local function normalizeAnimationId(text) text = trimText(text) if text == "" then return "Unknown" end local id = text:match("(%d+)") if id then return "rbxassetid://" .. id end return text end local function canUseScope(model) local mode = scopeModes[scopeIndex] if mode == "All" then return true elseif mode == "Self" then return model == player.Character elseif mode == "NPCs" then if not model then return false end if model == player.Character then return false end return Players:GetPlayerFromCharacter(model) == nil end return true end local function getSourceInfo(animator) local model = animator:FindFirstAncestorOfClass("Model") if model == player.Character then return "Self", player.Name, model end local plr = model and Players:GetPlayerFromCharacter(model) if plr then return "Player", plr.Name, model end if model then return "NPC", model.Name, model end return "Unknown", "Unknown", model end local function copyText(text) local ok = false if typeof(setclipboard) == "function" then ok = pcall(setclipboard, text) end copiedBox.Text = text return ok end local function clearLogRows() for _, child in ipairs(logsContainer:GetChildren()) do if child:IsA("Frame") and child:GetAttribute("IsLogRow") then child:Destroy() end end table.clear(logRows) table.clear(seenAnimationIds) updateStatus("Logs cleared") end local function enforceMaxRows() while #logRows > maxLogRows do local old = table.remove(logRows, 1) if old and old.Parent then local oldId = old:GetAttribute("AnimIdKey") if oldId then seenAnimationIds[oldId] = nil end old:Destroy() end end end local function addLogRow(sourceKind, sourceName, animName, animId) if seenAnimationIds[animId] then return end seenAnimationIds[animId] = true local row = Instance.new("Frame") row.Name = "LogRow" row.Size = UDim2.new(1, 0, 0, 62) row.BackgroundColor3 = Color3.fromRGB(32, 32, 32) row.BorderSizePixel = 0 row.Parent = logsContainer row:SetAttribute("IsLogRow", true) row:SetAttribute("AnimIdKey", animId) roundify(row, 10) local title = Instance.new("TextLabel") title.Size = UDim2.new(1, -70, 0, 24) title.Position = UDim2.new(0, 8, 0, 6) title.BackgroundTransparency = 1 title.TextXAlignment = Enum.TextXAlignment.Left title.Text = "[" .. sourceKind .. "] " .. sourceName .. " - " .. animName title.TextColor3 = Color3.fromRGB(255, 255, 255) title.TextScaled = true title.Font = Enum.Font.GothamBold title.Parent = row local idLabel = Instance.new("TextLabel") idLabel.Size = UDim2.new(1, -70, 0, 20) idLabel.Position = UDim2.new(0, 8, 0, 33) idLabel.BackgroundTransparency = 1 idLabel.TextXAlignment = Enum.TextXAlignment.Left idLabel.Text = animId idLabel.TextColor3 = Color3.fromRGB(220, 220, 220) idLabel.TextScaled = true idLabel.Font = Enum.Font.Gotham idLabel.Parent = row local copyButton = Instance.new("TextButton") copyButton.Size = UDim2.new(0, 52, 0, 36) copyButton.Position = UDim2.new(1, -60, 0.5, -18) copyButton.BackgroundColor3 = Color3.fromRGB(70, 110, 180) copyButton.Text = "Copy" copyButton.TextColor3 = Color3.fromRGB(255, 255, 255) copyButton.TextScaled = true copyButton.Font = Enum.Font.GothamBold copyButton.BorderSizePixel = 0 copyButton.Parent = row roundify(copyButton, 8) copyButton.MouseButton1Click:Connect(function() copyText(animId) copyButton.Text = "Done" task.delay(0.8, function() if copyButton and copyButton.Parent then copyButton.Text = "Copy" end end) end) table.insert(logRows, row) enforceMaxRows() end local function getAnimationName(track) local anim = track and track.Animation if anim and anim.Name and anim.Name ~= "" then return anim.Name end if track and track.Name and track.Name ~= "" and track.Name ~= "AnimationTrack" then return track.Name end return "Unknown" end local function getAnimationId(track) local anim = track and track.Animation if anim and anim.AnimationId and anim.AnimationId ~= "" then return normalizeAnimationId(anim.AnimationId) end return "Unknown" end local function logTrack(animator, track) if not animator or not track then return end local sourceKind, sourceName, model = getSourceInfo(animator) if not canUseScope(model) then return end local animId = getAnimationId(track) if animId == "Unknown" then return end local animName = getAnimationName(track) addLogRow(sourceKind, sourceName, animName, animId) updateStatus("Logged " .. animName) end local function scanCurrentTracks() clearLogRows() for _, obj in ipairs(workspace:GetDescendants()) do if obj:IsA("Animator") then if not hookedAnimators[obj] then local conn conn = obj.AnimationPlayed:Connect(function(track) logTrack(obj, track) end) hookedAnimators[obj] = conn end local ok, tracks = pcall(function() return obj:GetPlayingAnimationTracks() end) if ok and tracks then for _, track in ipairs(tracks) do logTrack(obj, track) end end end end updateStatus("Refreshed") end local function hookAnimator(animator) if hookedAnimators[animator] then return end local conn conn = animator.AnimationPlayed:Connect(function(track) logTrack(animator, track) end) hookedAnimators[animator] = conn end local function refreshScopeText() scopeButton.Text = "Scope: " .. scopeModes[scopeIndex] end scopeButton.MouseButton1Click:Connect(function() scopeIndex += 1 if scopeIndex > #scopeModes then scopeIndex = 1 end refreshScopeText() updateStatus("Scope set to " .. scopeModes[scopeIndex]) scanCurrentTracks() end) refreshButton.MouseButton1Click:Connect(function() scanCurrentTracks() end) clearButton.MouseButton1Click:Connect(function() clearLogRows() end) hideButton.MouseButton1Click:Connect(function() mainFrame.Visible = false smallButton.Visible = true end) smallButton.MouseButton1Click:Connect(function() mainFrame.Visible = true smallButton.Visible = false end) deleteButton.MouseButton1Click:Connect(function() for _, conn in pairs(hookedAnimators) do if conn then conn:Disconnect() end end table.clear(hookedAnimators) clearLogRows() screenGui:Destroy() end) local function makeDraggable(handle, target) local dragging = false local dragInput local dragStart local startPos handle.InputBegan:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then dragging = true dragStart = input.Position startPos = target.Position input.Changed:Connect(function() if input.UserInputState == Enum.UserInputState.End then dragging = false end end) end end) handle.InputChanged:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch then dragInput = input end end) UserInputService.InputChanged:Connect(function(input) if input == dragInput and dragging then local delta = input.Position - dragStart target.Position = UDim2.new( startPos.X.Scale, startPos.X.Offset + delta.X, startPos.Y.Scale, startPos.Y.Offset + delta.Y ) end end) end makeDraggable(titleBar, mainFrame) makeDraggable(smallButton, smallButton) workspace.DescendantAdded:Connect(function(obj) if obj:IsA("Animator") then hookAnimator(obj) task.defer(function() local ok, tracks = pcall(function() return obj:GetPlayingAnimationTracks() end) if ok and tracks then for _, track in ipairs(tracks) do logTrack(obj, track) end end end) end end) for _, obj in ipairs(workspace:GetDescendants()) do if obj:IsA("Animator") then hookAnimator(obj) end end updateStatus("Ready") scanCurrentTracks()