WalkBotV1
Key RequiredUniversal

WalkBotV1

Universal Scriptengineergamingblueengineergamingblue 470 views 12 executesUpdated Apr 22, 2026
4.2/ 5(6 votes)
5183% Positive
Lua Script•278 lines (7155 chars)
local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")

local player = Players.LocalPlayer

local function getCharacter()
    local character = player.Character
    if not character then return end

    local humanoid = character:FindFirstChildOfClass("Humanoid")
    local rootPart = character:FindFirstChild("HumanoidRootPart")

    if not humanoid or not rootPart then
        return
    end

    return character, humanoid, rootPart
end

local stuckState = 0
local lastJumpTime = 0
local JUMP_COOLDOWN = 0.8
local lastDirection = Vector3.new(1, 0, 0)

local NavConfig = {
    Active = true,
    Radius = 200,
    WaypointVisuals = true,
    StoppingDistance = 4,
    MaxStuckTime = 1.2
}

local PLAYER_JUMP_HEIGHT = 7
local PLAYER_WIDTH = 4

local camera = workspace.CurrentCamera

local activeLines = {}

local function clearAllMarkers()
    for _, l in pairs(activeLines) do
        if l then l:Destroy() end
    end
    activeLines = {}
end

local function removeLine(i)
    if activeLines[i] then
        activeLines[i]:Destroy()
        activeLines[i] = nil
    end
end

local function drawFullVisualPath(points)
    clearAllMarkers()
    if not NavConfig.WaypointVisuals then return end

    for i = 1, #points - 1 do
        local a = points[i].Position
        local b = points[i + 1].Position

        local dist = (b - a).Magnitude

        local part = Instance.new("Part")
        part.Anchored = true
        part.CanCollide = false
        part.Material = Enum.Material.Neon
        part.Color = Color3.fromRGB(255, 255, 0)
        part.Size = Vector3.new(0.2, 0.2, dist)
        part.CFrame = CFrame.lookAt(a, b) * CFrame.new(0, 0, -dist / 2)
        part.Parent = workspace

        table.insert(activeLines, part)
    end
end

local function lookAtCrumb(targetPos, speed)
    local _, _, rootPart = getCharacter()
    if not rootPart then return end

    speed = speed or 25

    local camPos = camera.CFrame.Position
    local dir = targetPos - camPos
    dir = Vector3.new(dir.X, 0, dir.Z)

    if dir.Magnitude < 0.001 then return end
    dir = dir.Unit

    local targetCF = CFrame.lookAt(camPos, camPos + dir)
    camera.CFrame = camera.CFrame:Lerp(targetCF, 1 / speed)
end

local function forceJump(humanoid)
    local now = os.clock()
    if now - lastJumpTime < JUMP_COOLDOWN then return end

    humanoid.Jump = true
    lastJumpTime = now
end

local function generateCrumbs(waypoints)
    local crumbs = {}

    for i = 1, #waypoints - 1 do
        table.insert(crumbs, {Position = waypoints[i].Position})
        table.insert(crumbs, {Position = waypoints[i + 1].Position})
    end

    table.insert(crumbs, {Position = waypoints[#waypoints].Position})

    return crumbs
end

local function hasTouchDamage(part)
    local name = part.Name:lower()

    if name:find("kill") then return true end
    if name:find("lava") then return true end
    if name:find("damage") then return true end
    if part:FindFirstChild("Damage") then return true end

    return false
end

local function isPositionDanger(pos)
    local boxSize = Vector3.new(6, 6, 6)

    local parts = workspace:GetPartBoundsInBox(CFrame.new(pos), boxSize)

    for _, p in ipairs(parts) do
        if p:GetAttribute("Hazard") == true then
            return true
        end

        if hasTouchDamage(p) then
            return true
        end
    end

    return false
end

local function buildDestination(mode, baseDir, rootPart)
    if mode == 0 then
        return rootPart.Position + Vector3.new(
            math.random(-NavConfig.Radius, NavConfig.Radius),
            0,
            math.random(-NavConfig.Radius, NavConfig.Radius)
        )
    elseif mode == 1 then
        local offset = baseDir.Unit * math.random(40, 120)
        return rootPart.Position + offset + Vector3.new(math.random(-20, 20), 0, math.random(-20, 20))
    else
        return rootPart.Position + Vector3.new(
            math.random(-NavConfig.Radius, NavConfig.Radius),
            0,
            math.random(-NavConfig.Radius, NavConfig.Radius)
        )
    end
end

local function followCrumbs(crumbs)
    local index = 1
    local stuckTime = 0

    while index <= #crumbs do
        if not NavConfig.Active then return false end

        local character, humanoid, rootPart = getCharacter()
        if not character or not humanoid or not rootPart then
            task.wait(0.1)
            return false
        end

        local crumb = crumbs[index]
        local nextLook = crumbs[math.min(index, #crumbs)]

        lookAtCrumb(nextLook.Position, 5)

        local target = crumb.Position
        local pos = rootPart.Position

        local delta = target - pos
        local planar = Vector3.new(delta.X, 0, delta.Z)

        if planar.Magnitude < NavConfig.StoppingDistance then
            local nextCrumb = crumbs[index + 1]

            if nextCrumb then
                local deltaY = nextCrumb.Position.Y - pos.Y
                if deltaY > 2 then
                    forceJump(humanoid)
                end
            end

            removeLine(index)
            index += 1
            stuckTime = 0
            continue
        end

        local dir = planar.Magnitude > 0 and planar.Unit or Vector3.zero
        humanoid:MoveTo(pos + dir * 8)

        if (pos - rootPart.Position).Magnitude > 0.15 then
            stuckTime = 0
        else
            stuckTime += 0.05
        end

        if stuckTime > NavConfig.MaxStuckTime then
            return false
        end

        task.wait()
    end

    return true
end

player.CharacterAdded:Connect(function()
    clearAllMarkers()
    stuckState = 0
    lastDirection = Vector3.new(1, 0, 0)
end)

task.spawn(function()
    print("NavBot SAFE VERSION")

    while true do
        if not NavConfig.Active then task.wait(1) continue end

        local character, humanoid, rootPart = getCharacter()
        if not character or not humanoid or not rootPart then
            task.wait(0.2)
            continue
        end

        local mode = stuckState % 3
        local destination = buildDestination(mode, lastDirection, rootPart)

        local path = PathfindingService:CreatePath({
            AgentRadius = 3,
            AgentHeight = 5,
            AgentCanJump = true,
            WaypointSpacing = 6
        })

        local success = pcall(function()
            path:ComputeAsync(rootPart.Position, destination)
        end)

        if success and path.Status == Enum.PathStatus.Success then
            local waypoints = path:GetWaypoints()
            local crumbs = generateCrumbs(waypoints)

            drawFullVisualPath(crumbs)

            local ok = followCrumbs(crumbs)

            if not ok then
                stuckState += 1
                lastDirection = (destination - rootPart.Position)
                clearAllMarkers()
                task.wait(0.1)
            else
                stuckState = 0
                clearAllMarkers()
                task.wait(0.2)
            end
        else
            stuckState += 1
            clearAllMarkers()
            task.wait(0.3)
        end
    end
end)

Features & Information

A script that creates a path in the game to automatically move like a person. It's open source, so you can use it, reprogram it, or improve it. If for any reason it doesn't start or work, please report it.

Community Comments (1)

GoogleChrome2GoogleChrome2Apr 22, 2026

In the next version, could you add a menu that allows control of certain functions? Like, for example, objectives????

More Scripts for Universal Scripts