Viewport Rendering - Optimizations

Okay, so I am using viewports to render the map in my game to make it look pixelated. (I know viewports suck, but it’s the only way I’ve found to achieve this look.) So I want to optimize my render function to stop a common issue I’ve found which is when I run the program it has a flash, of objects rendering in.

Code:

local OldFolder = Instance.new("Folder")

function Render()
	local newFolder = Instance.new("Folder", script.Parent.Parent)
	newFolder.Name = "NewFolder"

	local WorkChild = workspace:GetChildren()
	for _, v in ipairs(WorkChild) do
		if (((v:IsA('BasePart') or v:IsA("MeshPart")) and game.Players.LocalPlayer.Character.PrimaryPart.Position and (game.Players.LocalPlayer.Character.PrimaryPart.Position - v.Position).magnitude < 250) or 
			(not v:IsA('Terrain'))) and (not v:IsA("Folder")) and  (v ~= camPart) then
			v.Archivable = true
			local clone = v:Clone()
			clone.Parent = newFolder
		elseif v.ClassName == "Folder" then
			for index,child in pairs(v:GetChildren()) do
				if (((child:IsA('BasePart') or child:IsA("MeshPart")) and game.Players.LocalPlayer.Character.PrimaryPart.Position and (game.Players.LocalPlayer.Character.PrimaryPart.Position - child.Position).magnitude < 250) or 
					(not child:IsA('Terrain'))) and (child ~= camPart) then
					child.Archivable = true
					local clone = child:Clone()
					clone.Parent = newFolder
				end	
			end	
		end
	end

	if OldFolder then
		newFolder.Parent = script.Parent
		task.wait()
		OldFolder:Destroy()
	end
	OldFolder = newFolder
end

Video of the issue:

1 Like

the only way for it not to be extremely laggy is to not update every part every Render()
instead, you should only reinstance parts that move, or even better, just move them

2 Likes

what would be the best way to check that? or implement that?

Why would you clone everything over and over again? You can parent everything under the viewport, or even better a WorldModel. You then only move anything that will move such as other players, cars and such.

1 Like

what does a world model do? And yeah I get what you mean I might remake it with those changes.

It helps with animating characters as well as adding some physics to the viewport!

1 Like

could you send an article over, it will explain it better. Thanks

1 Like

Thank you so much, appreciate it.

1 Like

Thats mainly a limitation with ViewportFrames in general, the more you add to it, the more it will slow down.

1 Like

I added more optimizations in terms of how I’m rendering objects, and I was able to get a much smoother system, I will add more optimizations later on because honestly your idea is pretty hard to implement for me atleast.

So this is already much better, however a few things you need to do, you need to add a limit to your viewport frame, such as an area it can see, either a perimeter around the player or a distance from the camera, which in your case, perimeter around the player would be ideal.

You should add those inside the perimeter, then render it that way, like a chunk system!

1 Like

currently this is the updated code

function Render()
	local newFolder = Instance.new("Folder", script.Parent.Parent)
	newFolder.Name = "NewFolder"

	-- Prepare and clone objects into newFolder
	local WorkChild = workspace:GetChildren()
	for _, v in ipairs(WorkChild) do
		if v ~= camPart and not v:IsA("Folder") then
			if v:IsA('BasePart') or v:IsA("MeshPart") then
				if (game.Players.LocalPlayer.Character.PrimaryPart.Position - v.Position).magnitude < 150 then
					v.Archivable = true
					local clone = v:Clone()
					clone.Parent = newFolder
				end
			elseif v:IsA("Model") then
				v.Archivable = true
				local clone = v:Clone()
				clone.Parent = newFolder
			end
		elseif v.ClassName == "Folder" then
			for _, child in pairs(v:GetChildren()) do
				if child ~= camPart and not child:IsA("Folder") then
					if child:IsA('BasePart') or child:IsA("MeshPart") then
						if (game.Players.LocalPlayer.Character.PrimaryPart.Position - child.Position).magnitude < 150 then
							child.Archivable = true
							child:Clone().Parent = newFolder
						end
					elseif child:IsA("Model") then
						if child.PrimaryPart then
							if (game.Players.LocalPlayer.Character.PrimaryPart.Position - child.PrimaryPart.Position).magnitude < 150 then
								child.Archivable = true
								child:Clone().Parent = newFolder
							end
						else
							local part = child:FindFirstChildWhichIsA("BasePart")
							if part then
								if (game.Players.LocalPlayer.Character.PrimaryPart.Position - part.Position).magnitude < 150 then
									child.Archivable = true
									child:Clone().Parent = newFolder
								end
							end
						end
					end
				elseif child.Name == "AlwaysRender" then
					child.Archivable = true
					child:Clone().Parent = newFolder
				end
			end
		end
	end

Changes:

  • Trys to render a new frame less often
  • The render distance (needs a revamp probably with a GetPartBoundsInBox function usage)

but this idea, is much better but I can’t seem to visualize a way to implement it, could you start me off?