Phasing characters

I am trying to make a system where characters only such as NPCs, or other players have a custom load radius. For example, the game would only load characters within 50 studs of your own character. I would be able to detect when a character is phased in and do things such as load a nametag etc.

My first thought is if there is possibly a way to do this with streamingenabled to optimize the game rather than making a whole system myself.

2 Likes

You could probably try something like this…

ServerScript

local LOAD_RADIUS = 50
local nametagTemplate = nil

local function shouldLoadCharacter(player, character)
    local playerPosition = player.Character and player.Character.HumanoidRootPart.Position
    local characterPosition = character and character:FindFirstChild("HumanoidRootPart") and character.HumanoidRootPart.Position
    
    if playerPosition and characterPosition then
        local distance = (playerPosition - characterPosition).Magnitude
        return distance <= LOAD_RADIUS
    end
    
    return false
end

game:GetService("Players").PlayerAdded:Connect(function(player)
    player.CharacterAdded:Connect(function(character)
        character:WaitForChild("HumanoidRootPart") -- Wait for character to load
        
        local nametag = nametagTemplate:Clone()
        nametag.Parent = character
        
        player.CharacterRemoving:Connect(function()
            if nametag and nametag:IsDescendantOf(character) then
                nametag:Destroy()
            end
        end)
    end)
end)

game:GetService("RunService").Heartbeat:Connect(function()
    for _, player in pairs(game.Players:GetPlayers()) do
        local character = player.Character
        if character and shouldLoadCharacter(player, character) then
            character:WaitForChild("HumanoidRootPart")
            character.HumanoidRootPart.Anchored = false
        else
            if character and character:FindFirstChild("HumanoidRootPart") then
                character.HumanoidRootPart.Anchored = true
            end
        end
    end
end)

StarterPlayerScripts

local Player = game.Players.LocalPlayer
local playerCharacter = Player.Character

Player.CharacterAdded:Connect(function(character)
    playerCharacter = character
end)

game:GetService("RunService").RenderStepped:Connect(function()
    for _, character in pairs(game.Players:GetPlayers()) do
        if character ~= Player and playerCharacter and playerCharacter:FindFirstChild("HumanoidRootPart") then
            local distance = (playerCharacter.HumanoidRootPart.Position - character.Character.HumanoidRootPart.Position).Magnitude
            local nametag = character.Character:FindFirstChild("Nametag")
            
            if distance <= LOAD_RADIUS then
                if not nametag then
                    -- Load the nametag (you might want to customize this part)
                    local nametagClone = game.ServerStorage.NametagTemplate:Clone()
                    nametagClone.Parent = character.Character
                end
            else
                if nametag then
                    nametag:Destroy()
                end
            end
        end
    end
end)

Replace nil with the tag template.