Render Distance ServerScript problem

Currently I am having trouble creating a server-sided render distance system (the reason it’s in ServerScriptService is because my game’s server memory is out of control.)

Why am I using a Server-based rendering system

  1. The game’s server memory is using around 6GB of space (most of which comes from unanchored parts)
  2. StreamingEnabled with a MinimumRadius and TargetRadius of 64 isn’t cutting it. Surely it helps a bit; however, Opportunistic StreamOut Behavior results in my vehicles (they use A-Chassis) falling apart after re-rendering. LowMemory StreamOut Behavior still makes the game super dependent on resources, so that won’t work either.

What Exactly is the Problem?
The only problem I have to face now is getting models to spawn into the Workspace from a folder located in ReplicatedStorage, but ONLY if those models are within a 50 stud radius of ANY HumanoidRootPart found. This script works great when one player is in the server; however, 2+ players makes multiple HumanoidRootPart Positions, which makes a “flickering” effect for models that should be rendered around one player. Below is a video of what I mean by the term flickering:

Another Perspective


Say that the white neon parts are Players. Say that the blue parts are in a 50 stud radius of some player’s HumanoidRootPart. Say that the red parts are out of range, and shouldn’t be rendered. This is my overall goal for what I want accomplished.

Extra Information
Before giving you the script, there’s some other things you may want to consider:

  • This is a ServerScript located inside of ServerScriptService
  • There is a folder called “Bins” inside of the Workspace, which is where Models should be moved when rendered.
  • There is a folder called “RenderCache” inside of ReplicatedStorage, which is where Models should be moved when unrendered.

Code
Note that the areas I think are causing this problem are commented with specific info. I really appreciate all the help I can get, good luck!

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local workspace = game:GetService("Workspace")

local HumanoidRootParts = {}

function setAnchor(object, boolean) --This function isn't a problem, don't worry about it.
	if boolean == false then
		for i,v in pairs(object:GetDescendants()) do
			if v:IsA("BasePart") then
				v.Anchored = false
			end
		end
	else
		for i,v in pairs(object:GetDescendants()) do
			if v:IsA("BasePart") then
				v.Anchored = true
			end
		end
	end
end

game.Players.PlayerAdded:Connect(function(plr) --This function isn't a problem, don't worry about it.
	plr.CharacterAdded:Connect(function(char)
		char:WaitForChild("HumanoidRootPart")
		
		local HumanoidRootPart = char.HumanoidRootPart
		table.insert(HumanoidRootParts, HumanoidRootPart)
	end)
end)

game.Players.PlayerRemoving:Connect(function(plr) --This function isn't a problem, don't worry about it.
	plr.CharacterRemoving:Connect(function(char)
		if char:FindFirstChild("HumanoidRootPart") then
			local HumanoidRootPart = char.HumanoidRootPart
			table.remove(HumanoidRootParts, HumanoidRootPart)
		end
	end)
end)

local RenderDistance = 50
local Render = workspace:WaitForChild("Bins") --This is the folder where the rendered Models are pasted into
local RenderCache = ReplicatedStorage:WaitForChild("RenderCache") --This is the folder that "unrenders" the Models.
local Parts = {} --Table for Parts found within the Models to be rendered.

function Scan() --This function isn't a problem, don't worry about it.
	for _, Object in pairs(Render:GetDescendants()) do
		if Object:IsA("Model") then
			table.insert(Parts, Object)
			if Object.Parent:IsA("Folder") then
				Object.Parent = RenderCache
			end
		end
	end
end

function GetPart(Object) --This function isn't a problem, don't worry about it.
	if Object:IsA("BasePart") then
		return Object
	else
		for _, Obj in pairs(Object:GetChildren()) do
			return GetPart(Obj)
		end
	end
	return nil
end

function Update() --Please take a look at this function
	for _,v in pairs(Parts) do --Looks in the table of Parts{}
		local Part = GetPart(v) --Gets the parts found within the Parts{} table.
		
		if (Part) then --Checks if Part == true
			for index, value in ipairs(HumanoidRootParts) do --Loops through the HumanoidRootParts{} table. This 
				local Distance = (Part.CFrame.Position - value.CFrame.Position).Magnitude --Should I be using Region3 here?
				Distance = math.floor(Distance + 0.5) --Adds an extra 0.5 float value to ensure render accuracy.

 				if (Distance <= RenderDistance) then --**This is what's causing the render flickering, due to multiple HumanoidRootPart Positions being registered.**
					setAnchor(v, false)
					v.Parent = Render
				elseif Distance >= RenderDistance then
					setAnchor(v, true)
					v.Parent = RenderCache
 				end
			end
			

		end
	end
end


Scan()
while wait(1) do --Make fun of me all you want for using a while wait() loop, I have no other idea how I would end up doing this.
	Update()
end
1 Like

Ignore the rendered parts instead of changing it’s anchor and parent.

am having the same issue with my A-chassis cars did you find a fix for this yet?

No fix yet. Still looking for possible solutions.