
KeylessUniversal

-- Aim Assist (for YOUR Roblox game) + GUI + Target Dropdown (fixed layering + stays open)
-- StarterPlayerScripts (LocalScript)
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local localPlayer = Players.LocalPlayer
local camera = workspace.CurrentCamera
-- =========================
-- KEYBINDS (CHANGE ONLY HERE)
-- =========================
local KEY_TOGGLE_UI = Enum.KeyCode.P
local KEY_DELETE_UI = Enum.KeyCode.M
-- =========================
-- SETTINGS
-- =========================
local Settings = {
Enabled = true,
MaxFOV = 8, -- degrees
Smoothing = 0.18, -- 0..1
LeadTime = 0.12, -- seconds
MaxDistance = 600, -- studs
TargetPartName = "HumanoidRootPart", -- or "Head"
RequireRightMouse = false,
}
-- Target selection
local SelectedTargetUserId: number? = nil -- nil = Auto (closest in FOV)
-- =========================
-- Helpers
-- =========================
local function clampNumber(n, min, max)
n = tonumber(n)
if not n then return nil end
if n < min then return min end
if n > max then return max end
return n
end
local function safeGetCharacter(plr)
if plr and plr.Character and plr.Character.Parent then
return plr.Character
end
end
local function getTargetPart(char)
return char:FindFirstChild(Settings.TargetPartName) or char:FindFirstChild("Head")
end
local function angleBetween(a, b)
local d = math.clamp(a:Dot(b), -1, 1)
return math.deg(math.acos(d))
end
local function isAssistActive()
if not Settings.Enabled then return false end
if not Settings.RequireRightMouse then return true end
return UserInputService:IsMouseButtonPressed(Enum.UserInputType.MouseButton2)
end
local function isValidTarget(plr, part)
if not plr or plr == localPlayer then return false end
if not part then return false end
local hum = part.Parent and part.Parent:FindFirstChildOfClass("Humanoid")
return hum and hum.Health > 0
end
local function getPlayerByUserId(userId: number?)
if not userId then return nil end
for _, p in ipairs(Players:GetPlayers()) do
if p.UserId == userId then return p end
end
return nil
end
local function predictAimPoint(targetPart)
local pos = targetPart.Position
local v = targetPart.AssemblyLinearVelocity or Vector3.zero
return pos + (v * Settings.LeadTime)
end
-- =========================
-- GUI + Connections
-- =========================
local connections = {}
local destroyed = false
local gui: ScreenGui? = nil
local frame: Frame? = nil
local dropdownList: Frame? = nil
local dropdownBtn: TextButton? = nil
local dropdownOpen = false
local function connect(sig, fn)
local c = sig:Connect(fn)
table.insert(connections, c)
return c
end
local function disconnectAll()
for _, c in ipairs(connections) do
pcall(function() c:Disconnect() end)
end
table.clear(connections)
end
local function setUIVisible(visible: boolean)
if frame and frame.Parent then
frame.Visible = visible
if not visible and dropdownList then
dropdownList.Visible = false
dropdownOpen = false
end
end
end
local function toggleUI()
if frame and frame.Parent then
setUIVisible(not frame.Visible)
end
end
local function deleteUI()
if destroyed then return end
destroyed = true
disconnectAll()
if gui then pcall(function() gui:Destroy() end) end
gui, frame, dropdownList, dropdownBtn = nil, nil, nil, nil
end
local function createGUI()
gui = Instance.new("ScreenGui")
gui.Name = "AimAssistGUI"
gui.ResetOnSpawn = false
gui.ZIndexBehavior = Enum.ZIndexBehavior.Sibling -- IMPORTANT: lets ZIndex work across siblings
gui.Parent = localPlayer:WaitForChild("PlayerGui")
frame = Instance.new("Frame")
frame.Name = "Panel"
frame.Size = UDim2.new(0, 370, 0, 280)
frame.Position = UDim2.new(0, 20, 0, 120)
frame.BackgroundTransparency = 0.15
frame.BorderSizePixel = 0
frame.ZIndex = 1
frame.Parent = gui
local corner = Instance.new("UICorner")
corner.CornerRadius = UDim.new(0, 12)
corner.Parent = frame
local stroke = Instance.new("UIStroke")
stroke.Thickness = 1
stroke.Transparency = 0.4
stroke.Parent = frame
local title = Instance.new("TextLabel")
title.Size = UDim2.new(1, -46, 0, 28)
title.Position = UDim2.new(0, 8, 0, 6)
title.BackgroundTransparency = 1
title.TextXAlignment = Enum.TextXAlignment.Left
title.Font = Enum.Font.GothamBold
title.TextSize = 16
title.Text = "Aim Assist (Owner Tools)"
title.ZIndex = 2
title.Parent = frame
local closeBtn = Instance.new("TextButton")
closeBtn.Size = UDim2.new(0, 28, 0, 28)
closeBtn.Position = UDim2.new(1, -34, 0, 6)
closeBtn.BorderSizePixel = 0
closeBtn.BackgroundTransparency = 0.05
closeBtn.Font = Enum.Font.GothamBold
closeBtn.TextSize = 16
closeBtn.Text = "X"
closeBtn.ZIndex = 2
closeBtn.Parent = frame
local closeCorner = Instance.new("UICorner")
closeCorner.CornerRadius = UDim.new(0, 8)
closeCorner.Parent = closeBtn
local hint = Instance.new("TextLabel")
hint.Size = UDim2.new(1, -12, 0, 18)
hint.Position = UDim2.new(0, 8, 0, 34)
hint.BackgroundTransparency = 1
hint.TextXAlignment = Enum.TextXAlignment.Left
hint.Font = Enum.Font.Gotham
hint.TextSize = 12
hint.TextTransparency = 0.2
hint.Text = ("Keys: %s hide/show, %s delete UI. Dropdown refreshes every 10s.")
:format(KEY_TOGGLE_UI.Name, KEY_DELETE_UI.Name)
hint.ZIndex = 2
hint.Parent = frame
local function row(y, labelText, defaultText)
local label = Instance.new("TextLabel")
label.Size = UDim2.new(0, 180, 0, 26)
label.Position = UDim2.new(0, 8, 0, y)
label.BackgroundTransparency = 1
label.TextXAlignment = Enum.TextXAlignment.Left
label.Font = Enum.Font.Gotham
label.TextSize = 13
label.Text = labelText
label.ZIndex = 2
label.Parent = frame
local box = Instance.new("TextBox")
box.Size = UDim2.new(0, 160, 0, 26)
box.Position = UDim2.new(0, 200, 0, y)
box.BackgroundTransparency = 0.05
box.BorderSizePixel = 0
box.ClearTextOnFocus = false
box.Font = Enum.Font.Gotham
box.TextSize = 13
box.Text = defaultText
box.ZIndex = 2
box.Parent = frame
local boxCorner = Instance.new("UICorner")
boxCorner.CornerRadius = UDim.new(0, 8)
boxCorner.Parent = box
local boxStroke = Instance.new("UIStroke")
boxStroke.Thickness = 1
boxStroke.Transparency = 0.6
boxStroke.Parent = box
return box
end
-- Enabled toggle
local enabledBtn = Instance.new("TextButton")
enabledBtn.Size = UDim2.new(0, 160, 0, 28)
enabledBtn.Position = UDim2.new(0, 200, 0, 58)
enabledBtn.BorderSizePixel = 0
enabledBtn.Font = Enum.Font.GothamBold
enabledBtn.TextSize = 13
enabledBtn.ZIndex = 2
enabledBtn.Parent = frame
local btnCorner = Instance.new("UICorner")
btnCorner.CornerRadius = UDim.new(0, 8)
btnCorner.Parent = enabledBtn
local function refreshEnabledButton()
enabledBtn.Text = Settings.Enabled and "Enabled: ON" or "Enabled: OFF"
enabledBtn.BackgroundTransparency = Settings.Enabled and 0.05 or 0.2
end
refreshEnabledButton()
-- Dropdown label
local ddLabel = Instance.new("TextLabel")
ddLabel.Size = UDim2.new(0, 180, 0, 26)
ddLabel.Position = UDim2.new(0, 8, 0, 92)
ddLabel.BackgroundTransparency = 1
ddLabel.TextXAlignment = Enum.TextXAlignment.Left
ddLabel.Font = Enum.Font.Gotham
ddLabel.TextSize = 13
ddLabel.Text = "Target (dropdown)"
ddLabel.ZIndex = 2
ddLabel.Parent = frame
-- Dropdown button (base layer)
dropdownBtn = Instance.new("TextButton")
dropdownBtn.Size = UDim2.new(0, 160, 0, 26)
dropdownBtn.Position = UDim2.new(0, 200, 0, 92)
dropdownBtn.BackgroundTransparency = 0.05
dropdownBtn.BorderSizePixel = 0
dropdownBtn.Font = Enum.Font.Gotham
dropdownBtn.TextSize = 13
dropdownBtn.TextXAlignment = Enum.TextXAlignment.Left
dropdownBtn.Text = " Auto (closest in FOV) ▾"
dropdownBtn.ZIndex = 5
dropdownBtn.Parent = frame
local ddCorner = Instance.new("UICorner")
ddCorner.CornerRadius = UDim.new(0, 8)
ddCorner.Parent = dropdownBtn
local ddStroke = Instance.new("UIStroke")
ddStroke.Thickness = 1
ddStroke.Transparency = 0.6
ddStroke.Parent = dropdownBtn
-- Dropdown list (HIGH ZINDEX so it overlays everything)
dropdownList = Instance.new("Frame")
dropdownList.Name = "DropdownList"
dropdownList.Size = UDim2.new(0, 160, 0, 0)
dropdownList.Position = UDim2.new(0, 200, 0, 120)
dropdownList.BackgroundTransparency = 0.05
dropdownList.BorderSizePixel = 0
dropdownList.Visible = false
dropdownList.ClipsDescendants = true
dropdownList.ZIndex = 50
dropdownList.Parent = frame
local listCorner = Instance.new("UICorner")
listCorner.CornerRadius = UDim.new(0, 8)
listCorner.Parent = dropdownList
local listStroke = Instance.new("UIStroke")
listStroke.Thickness = 1
listStroke.Transparency = 0.6
listStroke.Parent = dropdownList
local uiList = Instance.new("UIListLayout")
uiList.SortOrder = Enum.SortOrder.LayoutOrder
uiList.Padding = UDim.new(0, 2)
uiList.Parent = dropdownList
local function setDropdownText(labelText)
if dropdownBtn then
dropdownBtn.Text = " " .. labelText .. " ▾"
end
end
local function makeOption(text, onClick)
local opt = Instance.new("TextButton")
opt.Size = UDim2.new(1, -6, 0, 24)
opt.BackgroundTransparency = 0.1
opt.BorderSizePixel = 0
opt.Font = Enum.Font.Gotham
opt.TextSize = 13
opt.TextXAlignment = Enum.TextXAlignment.Left
opt.Text = " " .. text
opt.ZIndex = 51
opt.Parent = dropdownList
local optCorner = Instance.new("UICorner")
optCorner.CornerRadius = UDim.new(0, 6)
optCorner.Parent = opt
connect(opt.MouseButton1Click, onClick)
return opt
end
-- IMPORTANT: Rebuild WITHOUT closing if it's open
local function rebuildDropdownOptions()
if not dropdownList or not dropdownList.Parent then return end
-- keep open/size state
local wasVisible = dropdownList.Visible
local priorSize = dropdownList.Size
-- clear old buttons only
for _, c in ipairs(dropdownList:GetChildren()) do
if c:IsA("TextButton") then c:Destroy() end
end
local options = {}
table.insert(options, {name = "Auto (closest in FOV)", userId = nil})
for _, p in ipairs(Players:GetPlayers()) do
if p ~= localPlayer then
table.insert(options, {name = p.DisplayName .. " (@" .. p.Name .. ")", userId = p.UserId})
end
end
for i, opt in ipairs(options) do
local btn = makeOption(opt.name, function()
SelectedTargetUserId = opt.userId
setDropdownText(opt.name)
-- close on user selection (but NOT on auto-refresh)
dropdownList.Visible = false
dropdownOpen = false
dropdownList.Size = UDim2.new(0, 160, 0, 0)
end)
btn.LayoutOrder = i
end
local rows = #options
local h = math.min(rows * 26 + 4, 200)
-- if it was open, keep it open and keep it expanded
if wasVisible then
dropdownList.Visible = true
dropdownOpen = true
dropdownList.Size = UDim2.new(0, 160, 0, h)
else
-- if it was closed, keep it closed (don’t pop open)
dropdownList.Visible = false
dropdownOpen = false
dropdownList.Size = priorSize -- usually 0 height
end
end
-- Dropdown click toggle
connect(dropdownBtn.MouseButton1Click, function()
if not dropdownList then return end
dropdownOpen = not dropdownOpen
dropdownList.Visible = dropdownOpen
if dropdownOpen then
rebuildDropdownOptions()
else
dropdownList.Size = UDim2.new(0, 160, 0, 0)
end
end)
-- Auto refresh every 10 seconds (doesn't close it)
task.spawn(function()
while not destroyed do
task.wait(10)
if destroyed then break end
rebuildDropdownOptions()
end
end)
-- If selected target leaves, revert to Auto (and keep dropdown open state unchanged)
connect(Players.PlayerRemoving, function(p)
if SelectedTargetUserId and p.UserId == SelectedTargetUserId then
SelectedTargetUserId = nil
setDropdownText("Auto (closest in FOV)")
end
end)
-- Numeric controls
local fovBox = row(128, "Max FOV (degrees)", tostring(Settings.MaxFOV))
local smoothBox = row(158, "Smoothing (0..1)", tostring(Settings.Smoothing))
local leadBox = row(188, "Lead Time (seconds)", tostring(Settings.LeadTime))
local distBox = row(218, "Max Distance (studs)", tostring(Settings.MaxDistance))
connect(enabledBtn.MouseButton1Click, function()
Settings.Enabled = not Settings.Enabled
refreshEnabledButton()
end)
connect(fovBox.FocusLost, function()
local v = clampNumber(fovBox.Text, 0.5, 60)
if v then Settings.MaxFOV = v; fovBox.Text = tostring(v) else fovBox.Text = tostring(Settings.MaxFOV) end
end)
connect(smoothBox.FocusLost, function()
local v = clampNumber(smoothBox.Text, 0, 1)
if v then Settings.Smoothing = v; smoothBox.Text = tostring(v) else smoothBox.Text = tostring(Settings.Smoothing) end
end)
connect(leadBox.FocusLost, function()
local v = clampNumber(leadBox.Text, 0, 1.5)
if v then Settings.LeadTime = v; leadBox.Text = tostring(v) else leadBox.Text = tostring(Settings.LeadTime) end
end)
connect(distBox.FocusLost, function()
local v = clampNumber(distBox.Text, 20, 5000)
if v then Settings.MaxDistance = v; distBox.Text = tostring(v) else distBox.Text = tostring(Settings.MaxDistance) end
end)
-- Dragging
local dragging = false
local dragStart, startPos
connect(title.InputBegan, function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1 then
dragging = true
dragStart = input.Position
startPos = frame.Position
connect(input.Changed, function()
if input.UserInputState == Enum.UserInputState.End then
dragging = false
end
end)
end
end)
connect(UserInputService.InputChanged, function(input)
if dragging and input.UserInputType == Enum.UserInputType.MouseMovement then
local delta = input.Position - dragStart
frame.Position = UDim2.new(
startPos.X.Scale, startPos.X.Offset + delta.X,
startPos.Y.Scale, startPos.Y.Offset + delta.Y
)
end
end)
-- X hides UI
connect(closeBtn.MouseButton1Click, function()
setUIVisible(false)
end)
-- Keybinds
connect(UserInputService.InputBegan, function(input, gameProcessed)
if gameProcessed then return end
if input.KeyCode == KEY_TOGGLE_UI then
toggleUI()
elseif input.KeyCode == KEY_DELETE_UI then
deleteUI()
end
end)
end
createGUI()
-- =========================
-- Target selection + Aim logic
-- =========================
local function getBestTargetAuto()
local camPos = camera.CFrame.Position
local camLook = camera.CFrame.LookVector.Unit
local bestPart = nil
local bestAngle = Settings.MaxFOV
for _, plr in ipairs(Players:GetPlayers()) do
if plr ~= localPlayer then
local char = safeGetCharacter(plr)
if char then
local part = getTargetPart(char)
if isValidTarget(plr, part) then
local toTarget = (part.Position - camPos)
local dist = toTarget.Magnitude
if dist <= Settings.MaxDistance then
local ang = angleBetween(camLook, toTarget.Unit)
if ang < bestAngle then
bestAngle = ang
bestPart = part
end
end
end
end
end
end
return bestPart
end
local function getLockedTargetPart()
local plr = getPlayerByUserId(SelectedTargetUserId)
if not plr then return nil end
local char = safeGetCharacter(plr)
if not char then return nil end
local part = getTargetPart(char)
if not isValidTarget(plr, part) then return nil end
-- gating (no yanking)
local camPos = camera.CFrame.Position
local camLook = camera.CFrame.LookVector.Unit
local toTarget = part.Position - camPos
if toTarget.Magnitude > Settings.MaxDistance then return nil end
if angleBetween(camLook, toTarget.Unit) > Settings.MaxFOV then return nil end
return part
end
connect(RunService.RenderStepped, function()
if destroyed then return end
if not isAssistActive() then return end
local targetPart
if SelectedTargetUserId then
targetPart = getLockedTargetPart()
else
targetPart = getBestTargetAuto()
end
if not targetPart then return end
local camPos = camera.CFrame.Position
local aimPoint = predictAimPoint(targetPart)
local desiredDir = (aimPoint - camPos).Unit
local currentDir = camera.CFrame.LookVector.Unit
if angleBetween(currentDir, desiredDir) > Settings.MaxFOV then return end
local newDir = currentDir:Lerp(desiredDir, Settings.Smoothing)
camera.CFrame = CFrame.new(camPos, camPos + newDir)
end)


![HanamiHub [Keyless] Universal Aimbot, ESP, Mobile](https://scriptblox.com/images/sb/0-1789661460161.png)
Tell me your prompt