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
- The game’s server memory is using around 6GB of space (most of which comes from unanchored parts)
- 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
