Universal Script – Avatar copi - Verified script for Universal Roblox
Key RequiredUniversal

Universal Script – Avatar copi

Universal ScriptMadaMada 1.1K views 4.6K executesUpdated Oct 21, 2026
Unrated
00
Lua Script•762 lines (38665 chars)
local SOURCE = [[
return function(INITIAL_SNAPSHOT, ENGINE_SOURCE)
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local HttpService = game:GetService("HttpService")
local player = Players.LocalPlayer
local env = getgenv and getgenv() or _G
local key = "LocalAvatarDisguise"

if env.LocalAvatarReplicatedIdle then env.LocalAvatarReplicatedIdle:Stop() end
if env[key] then env[key]:Stop() end

local state = {
    connections = {}, avatarConnections = {}, hidden = {}, tracks = {},
    version = 0, stopped = false, exportCount = 0
}
env[key] = state

function state:ClearAvatar()
    for _, c in ipairs(self.avatarConnections) do c:Disconnect() end
    table.clear(self.avatarConnections)
    if self.sharedTrack then
        pcall(function() self.sharedTrack:Stop(0.15) self.sharedTrack:Destroy() end)
        self.sharedTrack = nil
    end
    if self.sharedAnimation then self.sharedAnimation:Destroy() self.sharedAnimation = nil end
    for _, track in pairs(self.tracks) do
        pcall(function() track:Stop(0) track:Destroy() end)
    end
    table.clear(self.tracks)
    if self.model then self.model:Destroy() self.model = nil end
    for object, transparency in pairs(self.hidden) do
        if object.Parent then
            pcall(function() object.LocalTransparencyModifier = transparency end)
        end
    end
    table.clear(self.hidden)
end

function state:Clear() self:ClearAvatar() end

function state:Stop()
    self.stopped = true
    self.version = self.version + 1
    self.selectedSnapshot = nil
    self:ClearAvatar()
    for _, c in ipairs(self.connections) do c:Disconnect() end
    if self.gui then self.gui:Destroy() end
    if env[key] == self then env[key] = nil end
end

local function connect(signal, callback, avatar)
    local c = signal:Connect(callback)
    table.insert(avatar and state.avatarConnections or state.connections, c)
    return c
end

local function create(class, properties, parent)
    local object = Instance.new(class)
    for property, value in pairs(properties) do object[property] = value end
    object.Parent = parent
    return object
end

local function corner(object)
    create("UICorner", {CornerRadius = UDim.new(0, 9)}, object)
end

local gui = create("ScreenGui", {
    Name = "LocalAvatarChanger", ResetOnSpawn = false, DisplayOrder = 100,
    ZIndexBehavior = Enum.ZIndexBehavior.Sibling
}, player:WaitForChild("PlayerGui"))
state.gui = gui

local window = create("Frame", {
    Size = UDim2.fromOffset(300, 293), Position = UDim2.new(0.5, -150, 0.12, 0),
    BackgroundColor3 = Color3.fromRGB(24, 25, 32), BorderSizePixel = 0, Active = true
}, gui)
corner(window)
create("UIStroke", {Color = Color3.fromRGB(66, 68, 85)}, window)
local title = create("TextLabel", {
    Size = UDim2.new(1, -52, 0, 42), Position = UDim2.fromOffset(14, 0),
    BackgroundTransparency = 1, Text = "Avatar Changer + Export", Active = true,
    Font = Enum.Font.GothamBold, TextSize = 15, TextColor3 = Color3.new(1, 1, 1),
    TextXAlignment = Enum.TextXAlignment.Left
}, window)
local close = create("TextButton", {
    Size = UDim2.fromOffset(32, 32), Position = UDim2.new(1, -38, 0, 5),
    BackgroundTransparency = 1, Text = "×", Font = Enum.Font.GothamBold,
    TextSize = 25, TextColor3 = Color3.fromRGB(185, 188, 205)
}, window)
local input = create("TextBox", {
    Size = UDim2.new(1, -28, 0, 42), Position = UDim2.fromOffset(14, 49),
    BackgroundColor3 = Color3.fromRGB(35, 37, 48), BorderSizePixel = 0,
    Text = INITIAL_SNAPSHOT and INITIAL_SNAPSHOT.Username or "2Sh0rt4y0u",
    PlaceholderText = "Roblox username", ClearTextOnFocus = false,
    Font = Enum.Font.Gotham, TextSize = 15, TextColor3 = Color3.new(1, 1, 1)
}, window)
corner(input)

local function button(text, x, y, width, parent)
    local b = create("TextButton", {
        Size = UDim2.fromOffset(width or 131, 36), Position = UDim2.fromOffset(x, y),
        BackgroundColor3 = text == "Apply" and Color3.fromRGB(111, 83, 230)
            or Color3.fromRGB(47, 49, 63), BorderSizePixel = 0,
        Text = text, Font = Enum.Font.GothamBold, TextSize = 13,
        TextColor3 = Color3.new(1, 1, 1)
    }, parent or window)
    corner(b)
    return b
end
local applyButton = button("Apply", 14, 101)
local restoreButton = button("Restore", 155, 101)
local saveButton = button("Save script", 14, 146)
local copyButton = button("Copy script", 155, 146)
local idsButton = button("View all IDs", 14, 191, 272)
local status = create("TextLabel", {
    Size = UDim2.new(1, -28, 0, 52), Position = UDim2.fromOffset(14, 234),
    BackgroundTransparency = 1, Text = "Apply an avatar to capture its IDs.",
    TextWrapped = true, Font = Enum.Font.Gotham, TextSize = 12,
    TextColor3 = Color3.fromRGB(180, 185, 200)
}, window)

local function setStatus(message, failed)
    if state.stopped then return end
    status.Text = message
    status.TextColor3 = failed and Color3.fromRGB(255, 130, 145)
        or Color3.fromRGB(180, 185, 200)
end

local dragging, dragStart, startPosition
connect(title.InputBegan, function(event)
    if event.UserInputType == Enum.UserInputType.Touch
        or event.UserInputType == Enum.UserInputType.MouseButton1 then
        dragging, dragStart, startPosition = event, event.Position, window.Position
    end
end)
connect(UserInputService.InputChanged, function(event)
    if dragging and (event == dragging or (
        dragging.UserInputType == Enum.UserInputType.MouseButton1
        and event.UserInputType == Enum.UserInputType.MouseMovement)) then
        local delta = event.Position - dragStart
        window.Position = UDim2.new(startPosition.X.Scale, startPosition.X.Offset + delta.X,
            startPosition.Y.Scale, startPosition.Y.Offset + delta.Y)
    end
end)
connect(UserInputService.InputEnded, function(event)
    if event == dragging then dragging = nil end
end)

local preview = create("Frame", {
    Size = UDim2.new(0.9, 0, 0.8, 0), Position = UDim2.new(0.05, 0, 0.1, 0),
    BackgroundColor3 = Color3.fromRGB(24, 25, 32), BorderSizePixel = 0,
    Visible = false, ZIndex = 10
}, gui)
corner(preview)
local previewTitle = create("TextLabel", {
    Size = UDim2.new(1, -110, 0, 40), Position = UDim2.fromOffset(14, 0),
    BackgroundTransparency = 1, Text = "Export", Font = Enum.Font.GothamBold,
    TextSize = 15, TextColor3 = Color3.new(1, 1, 1),
    TextXAlignment = Enum.TextXAlignment.Left, ZIndex = 11
}, preview)
local previewClose = button("Close", 0, 0, 80, preview)
previewClose.Position = UDim2.new(1, -94, 0, 5)
previewClose.ZIndex = 11
local previewScroll = create("ScrollingFrame", {
    Size = UDim2.new(1, -28, 1, -62), Position = UDim2.fromOffset(14, 48),
    BackgroundColor3 = Color3.fromRGB(15, 17, 23), BorderSizePixel = 0,
    ScrollBarThickness = 6, CanvasSize = UDim2.new(),
    AutomaticCanvasSize = Enum.AutomaticSize.Y, ZIndex = 11
}, preview)
local previewText = create("TextBox", {
    Size = UDim2.new(1, -14, 0, 100), Position = UDim2.fromOffset(7, 5),
    AutomaticSize = Enum.AutomaticSize.Y, BackgroundTransparency = 1,
    Text = "", TextEditable = true, ClearTextOnFocus = false, MultiLine = true,
    TextWrapped = true, TextXAlignment = Enum.TextXAlignment.Left,
    TextYAlignment = Enum.TextYAlignment.Top, Font = Enum.Font.Code,
    TextSize = 13, TextColor3 = Color3.fromRGB(215, 220, 235), ZIndex = 12
}, previewScroll)
connect(previewClose.Activated, function() preview.Visible = false end)
local function showText(name, text)
    previewTitle.Text, previewText.Text = name, text
    previewScroll.CanvasPosition = Vector2.zero
    preview.Visible = true
end

local properties = {
    "BackAccessory", "BodyTypeScale", "ClimbAnimation", "DepthScale", "Face",
    "FaceAccessory", "FallAnimation", "FrontAccessory", "GraphicTShirt",
    "HairAccessory", "HatAccessory", "Head", "HeadColor", "HeadScale",
    "HeightScale", "IdleAnimation", "JumpAnimation", "LeftArm", "LeftArmColor",
    "LeftLeg", "LeftLegColor", "MoodAnimation", "NeckAccessory", "Pants",
    "ProportionScale", "RightArm", "RightArmColor", "RightLeg", "RightLegColor",
    "RunAnimation", "Shirt", "ShouldersAccessory", "StaticFacialAnimation",
    "SwimAnimation", "Torso", "TorsoColor", "UseAvatarSettings", "WaistAccessory",
    "WalkAnimation", "WidthScale"
}
local childProperties = {
    AccessoryDescription = {"AssetId", "AccessoryType", "IsLayered", "Order",
        "Position", "Rotation", "Scale", "Puffiness"},
    BodyPartDescription = {"AssetId", "BodyPart", "Color", "HeadShape"}
}

local function pack(value)
    local kind = typeof(value)
    if kind == "Color3" then
        return {__type = "Color3", Values = {value.R, value.G, value.B}}
    elseif kind == "Vector3" then
        return {__type = "Vector3", Values = {value.X, value.Y, value.Z}}
    elseif kind == "EnumItem" then
        return {__type = "EnumItem", Enum = tostring(value.EnumType):gsub("^Enum%.", ""), Name = value.Name}
    elseif kind == "table" then
        local result = {}
        for k, item in pairs(value) do result[k] = pack(item) end
        return result
    elseif kind == "string" or kind == "number" or kind == "boolean" then
        return value
    end
    error("Unsupported snapshot value: " .. kind)
end

local function unpackValue(value)
    if type(value) ~= "table" then return value end
    if value.__type == "Color3" then return Color3.new(value.Values[1], value.Values[2], value.Values[3]) end
    if value.__type == "Vector3" then return Vector3.new(value.Values[1], value.Values[2], value.Values[3]) end
    if value.__type == "EnumItem" then return Enum[value.Enum][value.Name] end
    local result = {}
    for k, item in pairs(value) do result[k] = unpackValue(item) end
    return result
end

local function capture(description, username, userId, rigType)
    local snapshot = {
        Version = 1, Username = username, UserId = userId, RigType = rigType.Name,
        CapturedAt = os.date("!%Y-%m-%dT%H:%M:%SZ"), Properties = {}, Children = {},
        Accessories = pack(description:GetAccessories(true)),
        Emotes = pack(description:GetEmotes()),
        EquippedEmotes = pack(description:GetEquippedEmotes())
    }
    for _, property in ipairs(properties) do
        local ok, value = pcall(function() return description[property] end)
        if ok then snapshot.Properties[property] = pack(value) end
    end
    for _, child in ipairs(description:GetChildren()) do
        local list = childProperties[child.ClassName]
        if list then
            local record = {ClassName = child.ClassName, Properties = {}}
            for _, property in ipairs(list) do
                local ok, value = pcall(function() return child[property] end)
                if ok then record.Properties[property] = pack(value) end
            end
            table.insert(snapshot.Children, record)
        end
    end
    return snapshot
end

local function restoreDescription(snapshot)
    assert(snapshot.Version == 1, "Unsupported snapshot version.")
    local description = Instance.new("HumanoidDescription")
    for property, value in pairs(snapshot.Properties) do
        local ok, err = pcall(function() description[property] = unpackValue(value) end)
        if not ok then warn("Snapshot property " .. property .. ": " .. tostring(err)) end
    end
    description:SetAccessories(unpackValue(snapshot.Accessories or {}), true)
    description:SetEmotes(unpackValue(snapshot.Emotes or {}))
    description:SetEquippedEmotes(unpackValue(snapshot.EquippedEmotes or {}))
    local used = {}
    for _, record in ipairs(snapshot.Children or {}) do
        local p = record.Properties
        local selected
        for _, child in ipairs(description:GetChildren()) do
            if not used[child] and child.ClassName == record.ClassName then
                if record.ClassName == "AccessoryDescription" then
                    if child.AssetId == p.AssetId
                        and child.AccessoryType == unpackValue(p.AccessoryType) then selected = child end
                elseif record.ClassName == "BodyPartDescription" then
                    if child.BodyPart == unpackValue(p.BodyPart) then selected = child end
                end
                if selected then break end
            end
        end
        if not selected then selected = Instance.new(record.ClassName) end
        used[selected] = true
        for property, value in pairs(p) do
            local ok, err = pcall(function() selected[property] = unpackValue(value) end)
            if not ok then warn("Snapshot child " .. property .. ": " .. tostring(err)) end
        end
        selected.Parent = description
    end
    return description
end

local defaults = {
    R15 = {idle = 507766666, walk = 507777826, run = 507767714, jump = 507765000,
        fall = 507767968, climb = 507765644, swim = 507784897, swimidle = 507785072, sit = 2506281703},
    R6 = {idle = 180435571, walk = 180426354, run = 180426354, jump = 125750702,
        fall = 180436148, climb = 180436334, sit = 178130996}
}
local animationProperties = {idle = "IdleAnimation", walk = "WalkAnimation", run = "RunAnimation",
    jump = "JumpAnimation", fall = "FallAnimation", climb = "ClimbAnimation", swim = "SwimAnimation"}
local function owningPart(attachment)
    local parent = attachment and attachment.Parent
    while parent and not parent:IsA("BasePart") do parent = parent.Parent end
    return parent
end
local function attachmentOffset(part, attachment)
    if attachment.Parent == part then return attachment.CFrame end
    return part.CFrame:ToObjectSpace(attachment.WorldCFrame)
end
local function bottomY(frame, size)
    return frame.Position.Y - (math.abs(frame.RightVector.Y) * size.X
        + math.abs(frame.UpVector.Y) * size.Y + math.abs(frame.LookVector.Y) * size.Z) * 0.5
end

local function loadAvatar(target)
    if type(target) == "string" then
        target = target:match("^%s*(.-)%s*$"):gsub("^@", "")
        if target == "" then setStatus("Enter a Roblox username.", true) return end
    end
    state.version = state.version + 1
    local version = state.version
    state.selectedSnapshot = nil
    state:ClearAvatar()
    setStatus(type(target) == "table" and "Loading saved avatar..." or "Loading @" .. target .. "...")
    local model, description
    local function cancelled() return state.stopped or version ~= state.version end
    local ok, err = pcall(function()
        local snapshot, rigType
        if type(target) == "table" then
            snapshot = target
            description = restoreDescription(snapshot)
            rigType = Enum.HumanoidRigType[snapshot.RigType]
        else
            local userId = Players:GetUserIdFromNameAsync(target)
            description = Players:GetHumanoidDescriptionFromUserIdAsync(userId)
            rigType = Enum.HumanoidRigType.R15
            local infoOk, info = pcall(function() return Players:GetCharacterAppearanceInfoAsync(userId) end)
            if infoOk and info.playerAvatarType == "R6" then rigType = Enum.HumanoidRigType.R6 end
            snapshot = capture(description, target, userId, rigType)
        end
        if cancelled() then return end
        local character = player.Character
        local humanoid = character and character:FindFirstChildOfClass("Humanoid")
        local root = character and character:FindFirstChild("HumanoidRootPart")
        assert(humanoid and root, "Your character is not ready.")
        model = Players:CreateHumanoidModelFromDescriptionAsync(description, rigType)
        if cancelled() or player.Character ~= character then model:Destroy() model = nil return end
        local visualHumanoid = model:FindFirstChildOfClass("Humanoid")
        local visualRoot = model:FindFirstChild("HumanoidRootPart")
        assert(visualHumanoid and visualRoot, "Avatar model is incomplete.")
        model.Name = "LocalAvatar_" .. snapshot.Username
        visualHumanoid.EvaluateStateMachine = false
        visualHumanoid.AutoRotate = false
        visualHumanoid.RequiresNeck = false
        visualHumanoid.BreakJointsOnDeath = false
        visualHumanoid.DisplayDistanceType = Enum.HumanoidDisplayDistanceType.None
        local parts, bodyParts, feet, graph, headParts, accessories, animationIds = {}, {}, {}, {}, {}, {}, {}
        local animate = model:FindFirstChild("Animate")
        for name, fallback in pairs(defaults[rigType.Name]) do
            local property = animationProperties[name]
            local id = property and description[property] or 0
            animationIds[name] = "rbxassetid://" .. tostring(id > 0 and id or fallback)
            local folder = animate and animate:FindFirstChild(name)
            local animation = folder and folder:FindFirstChildWhichIsA("Animation", true)
            if animation and animation.AnimationId ~= "" then animationIds[name] = animation.AnimationId end
            if snapshot.AnimationIds and snapshot.AnimationIds[name] then animationIds[name] = snapshot.AnimationIds[name] end
        end
        for _, object in ipairs(model:GetDescendants()) do
            if object:IsA("BaseScript") then object:Destroy()
            elseif object:IsA("BasePart") then
                object.Anchored, object.CanCollide, object.CanTouch, object.CanQuery = true, false, false, false
                object.Massless = true
                table.insert(parts, object)
                if object.Parent == model then
                    table.insert(bodyParts, object)
                    graph[object] = {}
                    if object.Name == "LeftFoot" or object.Name == "RightFoot"
                        or object.Name == "Left Leg" or object.Name == "Right Leg" then table.insert(feet, object)
                    elseif object.Name == "Head" then headParts[object] = true end
                end
            end
        end
        visualRoot.Transparency = 1
        local function addJoint(a, b, c0, c1, joint)
            if not graph[a] or not graph[b] then return end
            local edge = {a = a, b = b, c0 = c0, c1 = c1, joint = joint}
            table.insert(graph[a], edge) table.insert(graph[b], edge)
        end
        for _, joint in ipairs(model:GetDescendants()) do
            if joint:IsA("Motor6D") then addJoint(joint.Part0, joint.Part1, joint.C0, joint.C1, joint)
            elseif joint:IsA("AnimationConstraint") then
                local a, b = owningPart(joint.Attachment0), owningPart(joint.Attachment1)
                if graph[a] and graph[b] then
                    joint.IsKinematic = true
                    addJoint(a, b, attachmentOffset(a, joint.Attachment0), attachmentOffset(b, joint.Attachment1), joint)
                end
            end
        end
        local function solve(frame, animated)
            local poses, queue, index = {[visualRoot] = frame}, {visualRoot}, 1
            while index <= #queue do
                local part = queue[index]
                index = index + 1
                for _, edge in ipairs(graph[part]) do
                    local forward = part == edge.a
                    local other = forward and edge.b or edge.a
                    if not poses[other] then
                        local transform = animated and edge.joint.Transform or CFrame.identity
                        local relative = edge.c0 * transform * edge.c1:Inverse()
                        poses[other] = poses[part] * (forward and relative or relative:Inverse())
                        table.insert(queue, other)
                    end
                end
            end
            return poses
        end
        local neutral = solve(CFrame.identity, false)
        if rigType == Enum.HumanoidRigType.R15 then
            local groups = {}
            for _, part in ipairs(bodyParts) do
                for _, attachment in ipairs(part:GetChildren()) do
                    if attachment:IsA("Attachment") and attachment.Name:match("RigAttachment$") then
                        groups[attachment.Name] = groups[attachment.Name] or {}
                        table.insert(groups[attachment.Name], attachment)
                    end
                end
            end
            for _ = 1, #bodyParts do
                local repaired = false
                for name, group in pairs(groups) do
                    for _, a0 in ipairs(group) do
                        if neutral[a0.Parent] then
                            for _, a1 in ipairs(group) do
                                if a0.Parent ~= a1.Parent and not neutral[a1.Parent] then
                                    local motor = Instance.new("Motor6D")
                                    motor.Name = name:gsub("RigAttachment$", "")
                                    motor.Part0, motor.Part1, motor.C0, motor.C1 = a0.Parent, a1.Parent, a0.CFrame, a1.CFrame
                                    motor.Parent = a1.Parent
                                    addJoint(motor.Part0, motor.Part1, motor.C0, motor.C1, motor)
                                    repaired = true
                                    neutral = solve(CFrame.identity, false)
                                end
                            end
                        end
                    end
                end
                if not repaired then break end
            end
        end
        for _, part in ipairs(bodyParts) do assert(neutral[part], "Missing rig connection: " .. part.Name) end
        for _, accessory in ipairs(model:GetChildren()) do
            if accessory:IsA("Accessory") then
                local handle = accessory:FindFirstChild("Handle")
                local targetPart, offset
                if handle and handle:IsA("BasePart") then
                    for _, attachment in ipairs(handle:GetChildren()) do
                        if attachment:IsA("Attachment") then
                            for _, body in ipairs(bodyParts) do
                                local match = body:FindFirstChild(attachment.Name)
                                if match and match:IsA("Attachment") then
                                    targetPart, offset = body, match.CFrame * attachment.CFrame:Inverse()
                                    break
                                end
                            end
                        end
                        if targetPart then break end
                    end
                    if not targetPart then
                        local weld = handle:FindFirstChild("AccessoryWeld")
                        if weld and weld:IsA("Weld") then
                            if weld.Part0 == handle and graph[weld.Part1] then targetPart, offset = weld.Part1, weld.C1 * weld.C0:Inverse()
                            elseif weld.Part1 == handle and graph[weld.Part0] then targetPart, offset = weld.Part0, weld.C0 * weld.C1:Inverse() end
                        end
                    end
                    for _, part in ipairs(accessory:GetDescendants()) do
                        if part:IsA("BasePart") then
                            if targetPart then
                                table.insert(accessories, {part = part, target = targetPart,
                                    offset = offset * handle.CFrame:ToObjectSpace(part.CFrame)})
                                if targetPart.Name == "Head" then headParts[part] = true end
                            else part.Transparency = 1 end
                        end
                    end
                end
            end
        end
        local lowest = math.huge
        for _, foot in ipairs(feet) do lowest = math.min(lowest, bottomY(neutral[foot], foot.Size)) end
        local visualHeight = lowest < math.huge and -lowest or visualHumanoid.HipHeight + visualRoot.Size.Y / 2
        local originalHeight = humanoid.HipHeight + root.Size.Y / 2
        if humanoid.RigType == Enum.HumanoidRigType.R6 then
            local leg = character:FindFirstChild("Left Leg")
            originalHeight = originalHeight + (leg and leg.Size.Y or 2)
        end
        local baseOffset = visualHeight - originalHeight
        local rayParams = RaycastParams.new()
        rayParams.FilterType = Enum.RaycastFilterType.Exclude
        rayParams.FilterDescendantsInstances = {character, model}
        rayParams.IgnoreWater, rayParams.RespectCanCollide = true, true
        local function draw(grounded)
            local look = root.CFrame.LookVector
            local direction = Vector3.new(look.X, 0, look.Z)
            if direction.Magnitude < 0.001 then direction = Vector3.new(0, 0, -1) end
            local position = root.Position + Vector3.new(0, baseOffset, 0)
            local poses = solve(CFrame.lookAt(position, position + direction.Unit), true)
            local correction = 0
            if grounded then
                local hit = workspace:Raycast(root.Position + Vector3.new(0, 1, 0),
                    Vector3.new(0, -(originalHeight + 5), 0), rayParams)
                if hit then
                    local bottom = math.huge
                    for _, foot in ipairs(feet) do bottom = math.min(bottom, bottomY(poses[foot], foot.Size)) end
                    if bottom < math.huge then correction = hit.Position.Y + 0.025 - bottom end
                end
            end
            local shift = Vector3.new(0, correction, 0)
            for _, part in ipairs(bodyParts) do part.CFrame = poses[part] + shift end
            for _, binding in ipairs(accessories) do binding.part.CFrame = poses[binding.target] * binding.offset + shift end
        end
        draw(false)
        model.Parent = workspace
        state.model = model
        local animator = visualHumanoid:FindFirstChildOfClass("Animator")
        if not animator then animator = Instance.new("Animator") animator.Parent = visualHumanoid end
        for name, id in pairs(animationIds) do
            local animation = Instance.new("Animation")
            animation.Name, animation.AnimationId, animation.Parent = name, id, model
            local trackOk, track = pcall(function() return animator:LoadAnimation(animation) end)
            if trackOk then
                track.Looped = name ~= "jump"
                track.Priority = name == "idle" and Enum.AnimationPriority.Idle or Enum.AnimationPriority.Movement
                state.tracks[name] = track
            else warn("Unable to load animation " .. name .. ": " .. tostring(track)) end
        end
        local sharedStatus = "Shared idle unavailable"
        local originalAnimator = humanoid:FindFirstChildOfClass("Animator")
        if humanoid.RigType ~= visualHumanoid.RigType then sharedStatus = "Shared idle: R6/R15 mismatch"
        elseif originalAnimator and state.tracks.idle then
            local animation = Instance.new("Animation")
            animation.Name, animation.AnimationId, animation.Parent = "AvatarSharedIdle", animationIds.idle, character
            state.sharedAnimation = animation
            local sharedOk, track = pcall(function() return originalAnimator:LoadAnimation(animation) end)
            if sharedOk then
                track.Looped, track.Priority = true, Enum.AnimationPriority.Action
                state.sharedTrack, sharedStatus = track, "Shared idle enabled"
            else animation:Destroy() state.sharedAnimation = nil warn(tostring(track)) end
        end
        local currentAnimation
        local function pauseShared()
            if state.sharedTrack and state.sharedTrack.IsPlaying then state.sharedTrack:Stop(0.15) end
        end
        local function play(name, speed)
            if not state.tracks[name] then name = "idle" end
            local track = state.tracks[name]
            if not track then return end
            if currentAnimation ~= name then
                local previous = currentAnimation and state.tracks[currentAnimation]
                if previous then previous:Stop(0.15) end
                currentAnimation = name
                track:Play(0.15)
            elseif track.Looped and not track.IsPlaying then track:Play(0.15) end
            track:AdjustSpeed(speed or 1)
        end
        local function hide(object)
            if object:IsA("BasePart") or object:IsA("Decal") then
                if state.hidden[object] == nil then state.hidden[object] = object.LocalTransparencyModifier end
                object.LocalTransparencyModifier = 1
            end
        end
        for _, object in ipairs(character:GetDescendants()) do hide(object) end
        connect(character.DescendantAdded, hide, true)
        connect(RunService.PreSimulation, function()
            for _, part in ipairs(parts) do
                if part.Parent then part.Anchored, part.CanCollide, part.CanTouch, part.CanQuery = true, false, false, false end
            end
        end, true)
        play("idle")
        connect(RunService.PreRender, function()
            if not root.Parent or not model.Parent or player.Character ~= character then pauseShared() return end
            local movementState = humanoid:GetState()
            local grounded = humanoid.FloorMaterial ~= Enum.Material.Air and not humanoid.Sit
                and movementState ~= Enum.HumanoidStateType.Jumping and movementState ~= Enum.HumanoidStateType.Freefall
                and movementState ~= Enum.HumanoidStateType.Climbing and movementState ~= Enum.HumanoidStateType.Swimming
            draw(grounded)
            for object in pairs(state.hidden) do if object.Parent then object.LocalTransparencyModifier = 1 end end
            local camera, head = workspace.CurrentCamera, character:FindFirstChild("Head")
            local firstPerson = camera and head and (camera.CFrame.Position - head.Position).Magnitude < 1
            for part in pairs(headParts) do part.LocalTransparencyModifier = firstPerson and 1 or 0 end
            if humanoid.Health <= 0 then
                pauseShared()
                for _, track in pairs(state.tracks) do if track.IsPlaying then track:Stop(0.15) end end
                return
            end
            local velocity = root.AssemblyLinearVelocity
            local speed = Vector3.new(velocity.X, 0, velocity.Z).Magnitude
            local moving = humanoid.MoveDirection.Magnitude > 0.05
            if humanoid.Sit then play("sit")
            elseif movementState == Enum.HumanoidStateType.Jumping then play("jump")
            elseif movementState == Enum.HumanoidStateType.Freefall then play("fall")
            elseif movementState == Enum.HumanoidStateType.Climbing then play("climb", math.clamp(math.abs(velocity.Y) / 5, 0, 3))
            elseif movementState == Enum.HumanoidStateType.Swimming then
                if velocity.Magnitude > 1 then play("swim", math.clamp(velocity.Magnitude / 10, 0.2, 3)) else play("swimidle") end
            elseif moving and speed > 0.5 then
                if speed > 10 then play("run", math.clamp(speed / 16, 0.2, 3)) else play("walk", math.clamp(speed / 8, 0.2, 3)) end
            else play("idle") end
            local standing = movementState == Enum.HumanoidStateType.Running
                or movementState == Enum.HumanoidStateType.RunningNoPhysics or movementState == Enum.HumanoidStateType.Landed
            local localIdle = state.tracks.idle
            if state.sharedTrack and localIdle and localIdle.IsPlaying and grounded and standing
                and not humanoid.PlatformStand and not moving and speed < 0.75 and currentAnimation == "idle" then
                local shared = state.sharedTrack
                if not shared.IsPlaying then
                    shared:Play(0.2, 1, 1)
                    if shared.Length > 0 then shared.TimePosition = localIdle.TimePosition % shared.Length end
                end
                shared:AdjustSpeed(localIdle.Speed)
            else pauseShared() end
        end, true)
        snapshot.AnimationIds = animationIds
        state.selectedSnapshot = snapshot
        input.Text = snapshot.Username
        setStatus("Applied @" .. snapshot.Username .. " • " .. tostring(#snapshot.Accessories)
            .. " accessories captured\n" .. sharedStatus)
    end)
    if description then description:Destroy() end
    if not ok then
        if model then model:Destroy() end
        if not cancelled() then
            state:ClearAvatar()
            state.selectedSnapshot = nil
            setStatus(tostring(err):match("[^\n]+$") or "Loading failed.", true)
        end
        warn("Avatar changer: " .. tostring(err))
    end
end

local function longQuote(text)
    local equals = ""
    while (text .. "]" .. equals .. "]"):find("]" .. equals .. "]", 1, true) ~= #text + 1 do
        equals = equals .. "="
    end
    return "[" .. equals .. "[\n" .. text .. "]" .. equals .. "]"
end

local function exportScript()
    local snapshot = state.selectedSnapshot
    if not snapshot then setStatus("Apply an avatar before exporting.", true) return end
    local json = HttpService:JSONEncode(snapshot)
    return "local SNAPSHOT_JSON = " .. longQuote(json)
        .. "\nlocal SOURCE = " .. longQuote(ENGINE_SOURCE)
        .. "\nlocal compile = assert(loadstring, 'This script requires loadstring.')"
        .. "\nlocal run = assert(compile(SOURCE))()"
        .. "\nrun(game:GetService('HttpService'):JSONDecode(SNAPSHOT_JSON), SOURCE)\n"
end

local function idReport(snapshot)
    local lines = {"Username: " .. snapshot.Username, "UserId: " .. tostring(snapshot.UserId),
        "Rig: " .. snapshot.RigType, "Captured: " .. snapshot.CapturedAt, "", "BODY / CLOTHING / ANIMATION IDS"}
    local idProperties = {"Head", "Torso", "LeftArm", "RightArm", "LeftLeg", "RightLeg", "Face",
        "Shirt", "Pants", "GraphicTShirt", "IdleAnimation", "WalkAnimation", "RunAnimation",
        "JumpAnimation", "FallAnimation", "ClimbAnimation", "SwimAnimation", "MoodAnimation"}
    for _, name in ipairs(idProperties) do table.insert(lines, name .. ": " .. tostring(snapshot.Properties[name] or 0)) end
    table.insert(lines, "\nACCESSORIES: " .. tostring(#snapshot.Accessories))
    for index, entry in ipairs(unpackValue(snapshot.Accessories)) do
        table.insert(lines, tostring(index) .. ". " .. tostring(entry.AccessoryType)
            .. " | AssetId: " .. tostring(entry.AssetId) .. " | Layered: " .. tostring(entry.IsLayered)
            .. " | Order: " .. tostring(entry.Order or 0))
    end
    table.insert(lines, "\nRESOLVED PLAYBACK ANIMATIONS")
    local names = {}
    for name in pairs(snapshot.AnimationIds or {}) do table.insert(names, name) end
    table.sort(names)
    for _, name in ipairs(names) do table.insert(lines, name .. ": " .. snapshot.AnimationIds[name]) end
    table.insert(lines, "\nEMOTES")
    local emotes = unpackValue(snapshot.Emotes or {})
    local emoteNames = {}
    for name in pairs(emotes) do table.insert(emoteNames, name) end
    table.sort(emoteNames)
    for _, name in ipairs(emoteNames) do
        local ids = {}
        for _, id in ipairs(emotes[name]) do table.insert(ids, tostring(id)) end
        table.insert(lines, name .. ": " .. table.concat(ids, ", "))
    end
    table.insert(lines, "\nFULL SNAPSHOT JSON\n" .. HttpService:JSONEncode(snapshot))
    return table.concat(lines, "\n")
end

connect(applyButton.Activated, function() task.spawn(loadAvatar, input.Text) end)
connect(input.FocusLost, function(enterPressed) if enterPressed then task.spawn(loadAvatar, input.Text) end end)
connect(restoreButton.Activated, function()
    state.version = state.version + 1
    state.selectedSnapshot = nil
    state:ClearAvatar()
    setStatus("Original appearance and animations restored.")
end)
connect(close.Activated, function() state:Stop() end)
connect(idsButton.Activated, function()
    if not state.selectedSnapshot then setStatus("Apply an avatar first.", true) return end
    showText("Avatar IDs", idReport(state.selectedSnapshot))
end)
connect(copyButton.Activated, function()
    local scriptText = exportScript()
    if not scriptText then return end
    local clipboard = setclipboard or toclipboard
    if type(clipboard) == "function" then
        local ok = pcall(clipboard, scriptText)
        if ok then setStatus("Complete saved-avatar script copied.") return end
    end
    showText("Select and copy this script", scriptText)
    setStatus("Clipboard unavailable. Copy from the export window.")
end)
connect(saveButton.Activated, function()
    local scriptText = exportScript()
    if not scriptText then return end
    if type(writefile) ~= "function" then
        showText("Copy and save as .lua", scriptText)
        setStatus("File saving unavailable. Export opened for copying.")
        return
    end
    state.exportCount = state.exportCount + 1
    local s = state.selectedSnapshot
    local name = "Avatar_" .. s.Username:gsub("[^%w_]", "_") .. "_" .. tostring(s.UserId)
        .. "_" .. tostring(os.time()) .. "_" .. tostring(state.exportCount) .. ".lua"
    local path = name
    if type(makefolder) == "function" then
        local exists = type(isfolder) == "function" and isfolder("avatar_exports")
        if exists or pcall(makefolder, "avatar_exports") then path = "avatar_exports/" .. name end
    end
    local ok, err = pcall(writefile, path, scriptText)
    if not ok and path ~= name then path = name ok, err = pcall(writefile, path, scriptText) end
    if ok then setStatus("Saved: " .. path)
    else showText("Copy and save as .lua", scriptText) setStatus("Save failed. Export opened for copying.", true) warn(tostring(err)) end
end)
connect(player.CharacterAdded, function(character)
    local snapshot = state.selectedSnapshot
    state.version = state.version + 1
    local version = state.version
    state:ClearAvatar()
    if snapshot then
        task.spawn(function()
            local humanoid = character:WaitForChild("Humanoid", 15)
            local root = character:WaitForChild("HumanoidRootPart", 15)
            if humanoid and root and not state.stopped and state.version == version
                and player.Character == character then loadAvatar(snapshot) end
        end)
    end
end)
if INITIAL_SNAPSHOT then
    task.spawn(function()
        local character = player.Character or player.CharacterAdded:Wait()
        local humanoid = character:WaitForChild("Humanoid", 15)
        local root = character:WaitForChild("HumanoidRootPart", 15)
        if humanoid and root and not state.stopped and state.version == 0 then loadAvatar(INITIAL_SNAPSHOT) end
    end)
end
end
]]
local compile = assert(loadstring, "This script requires loadstring.")
local run = assert(compile(SOURCE))()
run(nil, SOURCE)

How to Execute Universal Script – Avatar copi

Step 1: Copy Code: Click the Copy Code button in the viewer above to grab the clean Lua loadstring.

Step 2: Launch Executor: Open a compatible, unpatched executor. If you need one, check our Roblox Executors Directory.

Step 3: Join Experience: Launch Roblox and join Universal Script.

Step 4: Attach & Run: Attach/inject your executor into the Roblox process, paste the code into the script tab, and press Execute.

Created By

Mada
Mada
Script Creator
View Author Profile

Features & Information

Execute Universal Script – Avatar copi. Key system required, created by Mada, updated Oct 21, 2026. Tested and working on supported executors.
#Free#Avatar

Script Changelog (1)

@MadaOct 21, 2026

Create script

Community Comments (0)

No comments yet for this script.

Frequently Asked Questions

How do I execute Universal Script – Avatar copi in Roblox?

To run Universal Script – Avatar copi, copy the Lua loadstring from the code viewer above, launch Roblox and join Universal Script, attach a working executor (such as Potassium, Solara, or Delta from our Executors directory), paste the code into your executor console, and click Execute.

Is Universal Script – Avatar copi keyless or does it require an access key?

Universal Script – Avatar copi requires an access key. You can retrieve the official key directly using the Get Script Key link provided above.

Is Universal Script – Avatar copi currently safe and working?

This script is active and operational. Always test scripts using a secondary (alt) Roblox account to safeguard your main profile against anti-cheat bans.