Reincarnation Teleportation
Key RequiredUniversal

Reincarnation Teleportation

Universal ScriptISOXTERIAISOXTERIA 571 views 1.9K executesUpdated Sep 18, 2026
Unrated
00
Lua Script•656 lines (21329 chars)
--[[
    Reincarnation Teleportation
    made by Vighnesh

    place waypoints anywhere, see em from far away with a beam,
    teleport back to em whenever. rename/delete if you mess up.

    v1  - basic waypoints + teleport
    v1.1 - fade transition + safe landing raycast (no more falling thru map)
    v1.2 - beam textures/colors, settings tab, reset button
    v1.3 - per-waypoint colors + off screen compass arrow + sorted dropdown

    drop this in StarterPlayerScripts (or wherever u load scripts from)
    heads up: rayfield changes their api sometimes, if Dropdown/Slider stuff
    breaks check https://github.com/SiriusSoftwareLtd/Rayfield
]]

local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local TweenService = game:GetService("TweenService")

local LocalPlayer = Players.LocalPlayer

local Rayfield = loadstring(game:HttpGet('https://sirius.menu/rayfield'))()

-- config, tweak these if u want
local CONFIG = {
    TeleportFadeTime = 0.5,
    SafeLandingOffset = 3,
    BeamHeight = 2000,
    ShowBeams = true,
    BeamTextureId = "", -- stick your own asset id here if u want a scrolling texture, leave blank otherwise
}

local Waypoints = {}
local SelectedWaypoint = nil
local WaypointCounter = 0
local IsTeleporting = false

-- colors cycle through this so waypoints don't all look the same
local BEAM_PALETTE = {
    Color3.fromRGB(60, 200, 255),  -- cyan
    Color3.fromRGB(255, 130, 80),  -- orange
    Color3.fromRGB(140, 255, 120), -- green
    Color3.fromRGB(255, 220, 80),  -- yellow
    Color3.fromRGB(200, 120, 255), -- purple
    Color3.fromRGB(255, 110, 190), -- pink
}

-- fade to black overlay, reused every teleport so we're not making a new gui each time
local FadeGui = Instance.new("ScreenGui")
FadeGui.Name = "RT_FadeGui"
FadeGui.IgnoreGuiInset = true
FadeGui.DisplayOrder = 999
FadeGui.ResetOnSpawn = false
FadeGui.Parent = LocalPlayer:WaitForChild("PlayerGui")

local FadeFrame = Instance.new("Frame")
FadeFrame.Name = "Fade"
FadeFrame.Size = UDim2.new(1, 0, 1, 0)
FadeFrame.BackgroundColor3 = Color3.new(0, 0, 0)
FadeFrame.BackgroundTransparency = 1
FadeFrame.BorderSizePixel = 0
FadeFrame.ZIndex = 999
FadeFrame.Parent = FadeGui

-- compass arrow, points at selected waypoint when it's off screen
local CompassGui = Instance.new("ScreenGui")
CompassGui.Name = "RT_CompassGui"
CompassGui.IgnoreGuiInset = true
CompassGui.ResetOnSpawn = false
CompassGui.DisplayOrder = 998
CompassGui.Parent = LocalPlayer:WaitForChild("PlayerGui")

local CompassArrow = Instance.new("TextLabel")
CompassArrow.Name = "CompassArrow"
CompassArrow.AnchorPoint = Vector2.new(0.5, 0.5)
CompassArrow.Size = UDim2.fromOffset(36, 36)
CompassArrow.BackgroundTransparency = 1
CompassArrow.Text = "▲"
CompassArrow.TextColor3 = Color3.fromRGB(60, 200, 255)
CompassArrow.TextStrokeTransparency = 0
CompassArrow.TextStrokeColor3 = Color3.new(0, 0, 0)
CompassArrow.Font = Enum.Font.GothamBold
CompassArrow.TextScaled = true
CompassArrow.Visible = false
CompassArrow.ZIndex = 998
CompassArrow.Parent = CompassGui

local function updateCompass()
    local hrp = LocalPlayer.Character and LocalPlayer.Character:FindFirstChild("HumanoidRootPart")
    if not SelectedWaypoint or not hrp then
        CompassArrow.Visible = false
        return
    end

    local camera = workspace.CurrentCamera
    if not camera then
        CompassArrow.Visible = false
        return
    end

    local viewportPoint, onScreen = camera:WorldToViewportPoint(SelectedWaypoint.Position)

    if onScreen and viewportPoint.Z > 0 then
        -- already on screen, don't need the arrow
        CompassArrow.Visible = false
        return
    end

    local viewportSize = camera.ViewportSize
    local center = Vector2.new(viewportSize.X / 2, viewportSize.Y / 2)
    local delta = Vector2.new(viewportPoint.X, viewportPoint.Y) - center

    if viewportPoint.Z < 0 then
        delta = -delta -- flip when point is behind camera, roblox does this weird thing
    end
    if delta.Magnitude < 1 then
        delta = Vector2.new(0, -1)
    end

    local angle = math.atan2(delta.Y, delta.X)
    local radius = math.min(center.X, center.Y) - 60

    CompassArrow.Position = UDim2.new(0.5, math.cos(angle) * radius, 0.5, math.sin(angle) * radius)
    CompassArrow.Rotation = math.deg(angle) + 90
    CompassArrow.TextColor3 = SelectedWaypoint.Color or Color3.fromRGB(60, 200, 255)
    CompassArrow.Visible = true
end

-- makes the beam + marker + label for a waypoint
local function createWaypointVisual(position, color)
    color = color or BEAM_PALETTE[1]
    local lightColor = color:Lerp(Color3.new(1, 1, 1), 0.5)

    local anchor = Instance.new("Part")
    anchor.Name = "RT_WaypointAnchor"
    anchor.Anchored = true
    anchor.CanCollide = false
    anchor.CanQuery = false
    anchor.CanTouch = false
    anchor.Transparency = 1
    anchor.Size = Vector3.new(1, 1, 1)
    anchor.Position = position
    anchor.Parent = workspace

    local topPart = Instance.new("Part")
    topPart.Name = "RT_WaypointTop"
    topPart.Anchored = true
    topPart.CanCollide = false
    topPart.CanQuery = false
    topPart.CanTouch = false
    topPart.Transparency = 1
    topPart.Size = Vector3.new(1, 1, 1)
    topPart.Position = position + Vector3.new(0, CONFIG.BeamHeight, 0)
    topPart.Parent = anchor

    local att0 = Instance.new("Attachment", anchor)
    local att1 = Instance.new("Attachment", topPart)

    local beam = Instance.new("Beam")
    beam.Name = "RT_Beam"
    beam.Attachment0 = att0
    beam.Attachment1 = att1
    beam.Width0 = 2
    beam.Width1 = 0.15
    beam.FaceCamera = true
    beam.LightEmission = 1
    beam.LightInfluence = 0
    beam.Segments = 25
    beam.Color = ColorSequence.new({
        ColorSequenceKeypoint.new(0, color),
        ColorSequenceKeypoint.new(0.5, lightColor),
        ColorSequenceKeypoint.new(1, Color3.fromRGB(255, 255, 255)),
    })
    beam.Transparency = NumberSequence.new({
        NumberSequenceKeypoint.new(0, 0.05),
        NumberSequenceKeypoint.new(0.85, 0.35),
        NumberSequenceKeypoint.new(1, 1),
    })
    if CONFIG.BeamTextureId ~= "" then
        beam.Texture = CONFIG.BeamTextureId
        beam.TextureMode = Enum.TextureMode.Wrap
        beam.TextureLength = 4
        beam.TextureSpeed = 1.2
    end
    beam.Enabled = CONFIG.ShowBeams
    beam.Parent = anchor

    local marker = Instance.new("Part")
    marker.Name = "RT_WaypointMarker"
    marker.Shape = Enum.PartType.Ball
    marker.Anchored = true
    marker.CanCollide = false
    marker.CanQuery = false
    marker.CanTouch = false
    marker.Material = Enum.Material.Neon
    marker.Color = color
    marker.Size = Vector3.new(1.6, 1.6, 1.6)
    marker.Position = position
    marker.Transparency = CONFIG.ShowBeams and 0 or 1
    marker.Parent = anchor

    local markerLight = Instance.new("PointLight")
    markerLight.Color = lightColor
    markerLight.Range = 16
    markerLight.Brightness = 2
    markerLight.Parent = marker

    local sparkles = Instance.new("ParticleEmitter")
    sparkles.Color = ColorSequence.new(lightColor)
    sparkles.Size = NumberSequence.new({
        NumberSequenceKeypoint.new(0, 0.4),
        NumberSequenceKeypoint.new(1, 0),
    })
    sparkles.Transparency = NumberSequence.new({
        NumberSequenceKeypoint.new(0, 0.2),
        NumberSequenceKeypoint.new(1, 1),
    })
    sparkles.Lifetime = NumberRange.new(1.5, 2.5)
    sparkles.Rate = 12
    sparkles.Speed = NumberRange.new(3, 5)
    sparkles.SpreadAngle = Vector2.new(15, 15)
    sparkles.Acceleration = Vector3.new(0, 4, 0)
    sparkles.Enabled = CONFIG.ShowBeams
    sparkles.Parent = marker

    local billboard = Instance.new("BillboardGui")
    billboard.Name = "RT_Billboard"
    billboard.Adornee = anchor
    billboard.AlwaysOnTop = true
    billboard.Size = UDim2.new(0, 220, 0, 56)
    billboard.StudsOffset = Vector3.new(0, 4, 0)
    billboard.MaxDistance = 100000
    billboard.Enabled = CONFIG.ShowBeams
    billboard.Parent = anchor

    local nameLabel = Instance.new("TextLabel")
    nameLabel.Name = "NameLabel"
    nameLabel.Size = UDim2.new(1, 0, 0.55, 0)
    nameLabel.BackgroundTransparency = 1
    nameLabel.TextColor3 = Color3.new(1, 1, 1)
    nameLabel.TextStrokeTransparency = 0
    nameLabel.Font = Enum.Font.GothamBold
    nameLabel.TextScaled = true
    nameLabel.Parent = billboard

    local distLabel = Instance.new("TextLabel")
    distLabel.Name = "DistanceLabel"
    distLabel.Size = UDim2.new(1, 0, 0.45, 0)
    distLabel.Position = UDim2.new(0, 0, 0.55, 0)
    distLabel.BackgroundTransparency = 1
    distLabel.TextColor3 = Color3.fromRGB(180, 220, 255)
    distLabel.TextStrokeTransparency = 0
    distLabel.Font = Enum.Font.Gotham
    distLabel.TextScaled = true
    distLabel.Parent = billboard

    return anchor, beam, marker, sparkles, billboard, nameLabel, distLabel
end

local function getHRP()
    local char = LocalPlayer.Character
    return char and char:FindFirstChild("HumanoidRootPart")
end

local RefreshDropdown -- gets set once we build the ui further down

local function findWaypointByName(name)
    for _, wp in ipairs(Waypoints) do
        if wp.Name == name then
            return wp
        end
    end
    return nil
end

local function placeWaypoint()
    local hrp = getHRP()
    if not hrp then
        Rayfield:Notify({ Title = "Reincarnation Teleportation", Content = "cant find your character yet, try again in a sec", Duration = 4 })
        return
    end

    local position = hrp.Position
    WaypointCounter += 1
    local defaultName = "Waypoint " .. WaypointCounter
    local color = BEAM_PALETTE[((WaypointCounter - 1) % #BEAM_PALETTE) + 1]

    local anchor, beam, marker, sparkles, billboard, nameLabel, distLabel = createWaypointVisual(position, color)
    nameLabel.Text = defaultName

    local data = {
        Name = defaultName,
        Position = position,
        Color = color,
        Anchor = anchor,
        Beam = beam,
        Marker = marker,
        Sparkles = sparkles,
        Billboard = billboard,
        NameLabel = nameLabel,
        DistanceLabel = distLabel,
    }

    table.insert(Waypoints, data)
    SelectedWaypoint = data
    if RefreshDropdown then RefreshDropdown(defaultName) end

    Rayfield:Notify({ Title = "Waypoint Placed", Content = defaultName .. " placed", Duration = 3 })
end

local function removeWaypoint(data)
    if not data then return end
    if data.Anchor then data.Anchor:Destroy() end

    for i, wp in ipairs(Waypoints) do
        if wp == data then
            table.remove(Waypoints, i)
            break
        end
    end

    if SelectedWaypoint == data then
        SelectedWaypoint = Waypoints[1]
    end

    if RefreshDropdown then
        RefreshDropdown(SelectedWaypoint and SelectedWaypoint.Name or nil)
    end
end

local function renameWaypoint(data, newName)
    if not data or not newName or newName == "" then return end
    if findWaypointByName(newName) then
        Rayfield:Notify({ Title = "Reincarnation Teleportation", Content = "already got a waypoint with that name", Duration = 3 })
        return
    end

    data.Name = newName
    data.NameLabel.Text = newName
    if RefreshDropdown then RefreshDropdown(newName) end
end

-- builds a filter list of every player's character so raycasts/overlap
-- checks don't land you on top of someone standing near the waypoint
local function getCharacterFilterList()
    local list = {}
    for _, player in ipairs(Players:GetPlayers()) do
        if player.Character then
            table.insert(list, player.Character)
        end
    end
    return list
end

-- checks if a spot has solid stuff overlapping it (used so we never drop ppl INTO geometry)
local function isPositionStuck(position)
    local overlapParams = OverlapParams.new()
    overlapParams.FilterType = Enum.RaycastFilterType.Exclude
    overlapParams.FilterDescendantsInstances = getCharacterFilterList()

    -- roughly the size of a standing character's lower half
    local checkSize = Vector3.new(2.5, 5, 2.5)
    local checkCFrame = CFrame.new(position + Vector3.new(0, 2.5, 0))

    local parts = workspace:GetPartBoundsInBox(checkCFrame, checkSize, overlapParams)
    for _, part in ipairs(parts) do
        if part.CanCollide then
            return true
        end
    end
    return false
end

-- nudges a position straight up until it's not overlapping anything solid, capped
-- so it can't run away and fling the player into the sky
local function unstickPosition(position)
    local attempts = 0
    local nudged = position
    while isPositionStuck(nudged) and attempts < 15 do
        nudged += Vector3.new(0, 1, 0)
        attempts += 1
    end
    return nudged
end

-- raycast down to find real ground so we don't teleport ppl into a wall/void.
-- this used to sometimes land people way too high (hit a leaf/railing/other
-- non-collidable clutter instead of the actual floor) or straight into the
-- ground (raycast missed entirely and fell back to the raw stored position).
-- fixed by: ignoring non-collidable junk, skipping past walls/ceilings to find
-- an actual floor-like surface, sanity-checking the result, and unsticking
-- the final spot if it still ends up overlapping something solid.
local function findSafeLandingPosition(position)
    local params = RaycastParams.new()
    params.FilterType = Enum.RaycastFilterType.Exclude
    params.FilterDescendantsInstances = getCharacterFilterList()
    params.RespectCanCollide = true -- skip decorative/non-collide junk entirely
    params.IgnoreWater = true       -- land on the real ground under water, not the surface

    local rayOrigin = position + Vector3.new(0, 300, 0)
    local landingPoint = nil

    -- step down through the world up to a few times: if we hit something
    -- that isn't floor-like (a wall, a ceiling, a steep roof) keep casting
    -- from just below that hit until we land on an actual floor or give up
    for attempt = 1, 4 do
        local result = workspace:Raycast(rayOrigin, Vector3.new(0, -5000, 0), params)
        if not result then
            break
        end

        if result.Normal.Y > 0.5 then
            -- normal points mostly upward, this is a floor, good to go
            landingPoint = result.Position
            break
        end

        -- not floor-like, dip below it and keep looking
        rayOrigin = result.Position - Vector3.new(0, 1, 0)
    end

    local candidate

    if landingPoint then
        -- sanity check: if the floor we found is wildly far from where the
        -- waypoint was originally placed, something's off (e.g. we skipped
        -- through into a basement) — don't trust it, use the stored spot instead
        if math.abs(landingPoint.Y - position.Y) > 300 then
            candidate = position + Vector3.new(0, CONFIG.SafeLandingOffset, 0)
        else
            candidate = landingPoint + Vector3.new(0, CONFIG.SafeLandingOffset, 0)
        end
    else
        -- raycast found nothing at all (void / unloaded terrain), fall back
        -- to the stored position
        candidate = position + Vector3.new(0, CONFIG.SafeLandingOffset, 0)
    end

    -- last line of defense: whatever we ended up with, make sure it's not
    -- actually overlapping solid geometry before we send the player there
    return unstickPosition(candidate)
end

local function teleportTo(data)
    if IsTeleporting or not data then return end
    local hrp = getHRP()
    if not hrp then return end

    IsTeleporting = true

    local fadeOut = TweenService:Create(
        FadeFrame,
        TweenInfo.new(CONFIG.TeleportFadeTime, Enum.EasingStyle.Sine, Enum.EasingDirection.Out),
        { BackgroundTransparency = 0 }
    )
    fadeOut:Play()
    fadeOut.Completed:Wait()

    local hrpNow = getHRP() -- character might've reset mid fade, check again
    if hrpNow then
        local safePosition = findSafeLandingPosition(data.Position)
        hrpNow.CFrame = CFrame.new(safePosition)
    end

    task.wait(0.1)

    local fadeIn = TweenService:Create(
        FadeFrame,
        TweenInfo.new(CONFIG.TeleportFadeTime, Enum.EasingStyle.Sine, Enum.EasingDirection.In),
        { BackgroundTransparency = 1 }
    )
    fadeIn:Play()
    fadeIn.Completed:Wait()

    IsTeleporting = false
end

-- ui time

local Window = Rayfield:CreateWindow({
    Name = "Reincarnation Teleportation",
    LoadingTitle = "Reincarnation Teleportation",
    LoadingSubtitle = "Waypoint Beacon System",
    ConfigurationSaving = { Enabled = false },
})

local Tab = Window:CreateTab("Waypoints", 4483362458)

Tab:CreateSection("Create")

Tab:CreateButton({
    Name = "Place Waypoint Here",
    Callback = placeWaypoint,
})

Tab:CreateSection("Manage")

local Dropdown = Tab:CreateDropdown({
    Name = "Select Waypoint",
    Options = {},
    CurrentOption = {},
    MultipleOptions = false,
    Callback = function(option)
        local name = option
        if type(option) == "table" then
            name = option[1]
        end
        SelectedWaypoint = findWaypointByName(name)
    end,
})

RefreshDropdown = function(selectName)
    -- closest first so the list actually stays useful once u have a bunch
    local sorted = table.clone(Waypoints)
    local hrp = getHRP()
    if hrp then
        table.sort(sorted, function(a, b)
            return (hrp.Position - a.Position).Magnitude < (hrp.Position - b.Position).Magnitude
        end)
    end

    local names = {}
    for _, wp in ipairs(sorted) do
        table.insert(names, wp.Name)
    end

    if Dropdown.Refresh then
        Dropdown:Refresh(names, true)
    elseif Dropdown.Set then
        Dropdown:Set(names)
    end

    if selectName and Dropdown.Set then
        Dropdown:Set(selectName)
    end
end

local DistanceLabel = Tab:CreateLabel("Distance: —")

Tab:CreateButton({
    Name = "Teleport to Selected",
    Callback = function()
        if IsTeleporting then return end
        if SelectedWaypoint then
            task.spawn(teleportTo, SelectedWaypoint)
        else
            Rayfield:Notify({ Title = "Reincarnation Teleportation", Content = "nothing selected", Duration = 3 })
        end
    end,
})

Tab:CreateInput({
    Name = "Rename Selected Waypoint",
    PlaceholderText = "new name...",
    RemoveTextAfterFocusLost = true,
    Callback = function(text)
        if SelectedWaypoint then
            renameWaypoint(SelectedWaypoint, text)
        else
            Rayfield:Notify({ Title = "Reincarnation Teleportation", Content = "nothing selected", Duration = 3 })
        end
    end,
})

Tab:CreateButton({
    Name = "Delete Selected Waypoint",
    Callback = function()
        if SelectedWaypoint then
            removeWaypoint(SelectedWaypoint)
        else
            Rayfield:Notify({ Title = "Reincarnation Teleportation", Content = "nothing selected", Duration = 3 })
        end
    end,
})

Tab:CreateSection("Settings")

local DEFAULT_SHOW_BEAMS = true
local DEFAULT_FADE_TIME = 0.5

local BeamsToggle
BeamsToggle = Tab:CreateToggle({
    Name = "Show Beams",
    CurrentValue = DEFAULT_SHOW_BEAMS,
    Callback = function(value)
        CONFIG.ShowBeams = value
        for _, wp in ipairs(Waypoints) do
            wp.Beam.Enabled = value
            wp.Billboard.Enabled = value
            wp.Sparkles.Enabled = value
            wp.Marker.Transparency = value and 0 or 1
        end
    end,
})

local FadeSlider
FadeSlider = Tab:CreateSlider({
    Name = "Teleport Fade Time (Default: 0.5s)",
    Range = { 0.1, 2 },
    Increment = 0.1,
    Suffix = "s",
    CurrentValue = DEFAULT_FADE_TIME,
    Callback = function(value)
        CONFIG.TeleportFadeTime = value
    end,
})

Tab:CreateButton({
    Name = "Reset Settings to Default",
    Callback = function()
        CONFIG.ShowBeams = DEFAULT_SHOW_BEAMS
        CONFIG.TeleportFadeTime = DEFAULT_FADE_TIME

        for _, wp in ipairs(Waypoints) do
            wp.Beam.Enabled = DEFAULT_SHOW_BEAMS
            wp.Billboard.Enabled = DEFAULT_SHOW_BEAMS
            wp.Sparkles.Enabled = DEFAULT_SHOW_BEAMS
            wp.Marker.Transparency = DEFAULT_SHOW_BEAMS and 0 or 1
        end

        if BeamsToggle.Set then BeamsToggle:Set(DEFAULT_SHOW_BEAMS) end
        if FadeSlider.Set then FadeSlider:Set(DEFAULT_FADE_TIME) end

        Rayfield:Notify({ Title = "Reincarnation Teleportation", Content = "settings reset (fade time back to 0.5s)", Duration = 3 })
    end,
})

-- distance labels update every ~0.2s, no need to do it every single frame
local accumulated = 0
local UPDATE_INTERVAL = 0.2

RunService.Heartbeat:Connect(function(dt)
    accumulated += dt
    if accumulated < UPDATE_INTERVAL then return end
    accumulated = 0

    local hrp = getHRP()
    if not hrp then return end

    for _, wp in ipairs(Waypoints) do
        local dist = (hrp.Position - wp.Position).Magnitude
        wp.DistanceLabel.Text = string.format("%d studs", math.floor(dist))
    end

    if SelectedWaypoint then
        local dist = (hrp.Position - SelectedWaypoint.Position).Magnitude
        DistanceLabel:Set("Distance: " .. math.floor(dist) .. " studs (" .. SelectedWaypoint.Name .. ")")
    else
        DistanceLabel:Set("Distance: —")
    end
end)

-- compass tho needs to run every frame or it'll look choppy when u spin the camera
RunService.RenderStepped:Connect(updateCompass)

Features & Information

Reincarnation Teleportation — place glowing waypoint beacons anywhere in the world, see them from far away with color-coded beams and an off-screen compass, then teleport back instantly with a smooth fade transition. Rename or delete waypoints anytime.
#Utility

Community Comments (2)

.

.

More Scripts for Universal Scripts