Follow command
Key RequiredUniversal

Follow command

Universal Scriptforeverinaloopforeverinaloop 57 views 65 executesUpdated Jul 16, 2026
Unrated
00
Lua Script•209 lines (8360 chars)
-- Ultra-Smart Hybrid Follower (With "NUH UH" Ground Recovery Command)
local Players = game:GetService("Players")
local PathfindingService = game:GetService("PathfindingService")
local RunService = game:GetService("RunService")

local localPlayer = Players.LocalPlayer
local targetPlayer = nil
local followConnection = nil
local bodyVelocity = nil
local bodyGyro = nil

-- Configuration
local STUCK_TIME_LIMIT = 0.4
local AIR_THRESHOLD = 5 

local path = PathfindingService:CreatePath({
    AgentRadius = 1.5,
    AgentHeight = 4.5,
    AgentCanJump = false, 
    AgentSlope = 45
})

local function removeFlightForces()
    if bodyVelocity then bodyVelocity:Destroy(); bodyVelocity = nil end
    if bodyGyro then bodyGyro:Destroy(); bodyGyro = nil end
end

-- Safely finds the closest solid ground surface underneath the character
local function teleportToNearestGround(rootPart)
    local raycastParams = RaycastParams.new()
    raycastParams.FilterType = Enum.RaycastFilterType.Exclude
    raycastParams.FilterDescendantsInstances = {rootPart.Parent}
    
    -- Cast a long ray straight down (up to 500 studs) to find a floor
    local raycastResult = workspace:Raycast(rootPart.Position, Vector3.new(0, -500, 0), raycastParams)
    
    if raycastResult then
        -- Snap to the intersection position + a minor upward offset so your feet don't clip into the floor
        rootPart.CFrame = CFrame.new(raycastResult.Position + Vector3.new(0, 3, 0))
    end
end

local function stopFollowing(forceGroundSnap)
    if followConnection then followConnection:Disconnect(); followConnection = nil end
    removeFlightForces()
    targetPlayer = nil
    
    local myChar = localPlayer.Character
    if myChar then
        local myHumanoid = myChar:FindFirstChildOfClass("Humanoid")
        local myRoot = myChar:FindFirstChild("HumanoidRootPart")
        if myHumanoid and myRoot then 
            myHumanoid:MoveTo(myRoot.Position) 
            myHumanoid.WalkSpeed = 16 
            
            -- If triggered by "NUH UH" while mid-air, snap safely to the solid ground below
            if forceGroundSnap then
                teleportToNearestGround(myRoot)
            end
        end
    end
end

local function hasLineOfSight(startPos, endPos, character)
    local raycastParams = RaycastParams.new()
    raycastParams.FilterType = Enum.RaycastFilterType.Exclude
    raycastParams.FilterDescendantsInstances = {character, targetPlayer.Character}
    local rayDirection = (endPos - startPos)
    return workspace:Raycast(startPos + Vector3.new(0,1,0), rayDirection, raycastParams) == nil
end

local function isFlying(rootPart)
    local raycastParams = RaycastParams.new()
    raycastParams.FilterType = Enum.RaycastFilterType.Exclude
    raycastParams.FilterDescendantsInstances = {rootPart.Parent}
    local result = workspace:Raycast(rootPart.Position, Vector3.new(0, -AIR_THRESHOLD, 0), raycastParams)
    return result == nil
end

local function startFollowing(playerToFollow)
    targetPlayer = playerToFollow
    if followConnection then followConnection:Disconnect() end
    
    local myChar = localPlayer.Character
    local targetChar = targetPlayer.Character
    if myChar and targetChar then
        local myRoot = myChar:FindFirstChild("HumanoidRootPart")
        local targetRoot = targetChar:FindFirstChild("HumanoidRootPart")
        if myRoot and targetRoot then
            myRoot.CFrame = targetRoot.CFrame * CFrame.new(0, 0, 2) 
        end
    end
    
    local lastPos = Vector3.new()
    local stuckTimer = 0
    
    followConnection = RunService.Heartbeat:Connect(function()
        local myChar = localPlayer.Character
        local targetChar = targetPlayer.Character
        
        if myChar and targetChar then
            local myHumanoid = myChar:FindFirstChildOfClass("Humanoid")
            local targetHumanoid = targetChar:FindFirstChildOfClass("Humanoid")
            local myRoot = myChar:FindFirstChild("HumanoidRootPart")
            local targetRoot = targetChar:FindFirstChild("HumanoidRootPart")
            
            if myHumanoid and targetHumanoid and myRoot and targetRoot then
                myHumanoid.Jump = false 
                
                local targetSpeed = targetHumanoid.WalkSpeed
                myHumanoid.WalkSpeed = targetSpeed
                
                local standTargetCFrame = targetRoot.CFrame * CFrame.new(0, 0, 2)
                local standTargetPos = standTargetCFrame.Position
                local myPos = myRoot.Position
                
                -- AIR FLIGHT MODE
                if isFlying(targetRoot) then
                    if not bodyVelocity then
                        bodyVelocity = Instance.new("BodyVelocity")
                        bodyVelocity.MaxForce = Vector3.new(4e5, 4e5, 4e5)
                        bodyVelocity.Velocity = Vector3.new(0,0,0)
                        bodyVelocity.Parent = myRoot
                    end
                    if not bodyGyro then
                        bodyGyro = Instance.new("BodyGyro")
                        bodyGyro.MaxTorque = Vector3.new(4e5, 4e5, 4e5)
                        bodyGyro.CFrame = targetRoot.CFrame
                        bodyGyro.Parent = myRoot
                    end
                    
                    local direction = (standTargetPos - myPos)
                    local distance = direction.Magnitude
                    
                    if distance > 0.5 then
                        bodyVelocity.Velocity = direction.Unit * math.clamp(distance * 5, targetSpeed, targetSpeed * 2)
                    else
                        bodyVelocity.Velocity = Vector3.new(0,0,0)
                    end
                    bodyGyro.CFrame = targetRoot.CFrame
                    
                -- GROUND PATHFINDING MODE
                else
                    removeFlightForces()
                    
                    if (myPos - lastPos).Magnitude < 0.2 then
                        stuckTimer = stuckTimer + RunService.Heartbeat:Wait()
                        if stuckTimer > STUCK_TIME_LIMIT then
                            myHumanoid:MoveTo(standTargetPos + Vector3.new(math.random(-1,1), 0, math.random(-1,1))) 
                            stuckTimer = 0
                        end
                    else
                        stuckTimer = 0
                    end
                    lastPos = myPos
                    
                    if hasLineOfSight(myPos, standTargetPos, myChar) then
                        myHumanoid:MoveTo(standTargetPos)
                    else
                        local success, _ = pcall(function()
                            path:ComputeAsync(myPos, standTargetPos)
                        end)
                        
                        if success and path.Status == Enum.PathStatus.Success then
                            local waypoints = path:GetWaypoints()
                            if #waypoints >= 2 then
                                myHumanoid:MoveTo(waypoints.Position)
                            else
                                myHumanoid:MoveTo(standTargetPos)
                            end
                        else
                            myHumanoid:MoveTo(standTargetPos)
                        end
                    end
                end
            end
        else
            stopFollowing(false)
        end
    end)
end

-- Universal Chat Interpreter
local function onPlayerChatted(player, message)
    local cleanMessage = message:lower():gsub("[%[%]]", ""):gsub("%s+", " "):match("^%s*(.-)%s*$")
    
    -- SELF COMMAND CHECK: Triggers only if YOU say it
    if player == localPlayer then
        if cleanMessage == "nuh uh" then
            -- Stops tracking and forces a down-ray ground drop check
            stopFollowing(true)
        end
        return
    end 
    
    -- TARGET COMMANDS: Triggers if other players say them
    if cleanMessage == ":follow" then
        startFollowing(player)
    elseif cleanMessage == ":stop" then
        stopFollowing(false)
    end
end

for _, player in ipairs(Players:GetPlayers()) do
    player.Chatted:Connect(function(message) onPlayerChatted(player, message) end)
end
Players.PlayerAdded:Connect(function(player)
    player.Chatted:Connect(function(message) onPlayerChatted(player, message) end)
end)

Features & Information

i made this with ai please don't be made at me im new too this stuff :C
#*

Community Comments (0)

No comments yet for this script.

More Scripts for Universal Scripts