PartOperation:SubstituteGeometry() still causes flickering under certain conditions

To keep this as concise as possible, I will be following the format generated when a post is going to be added.

  1. What do you want to achieve? Keep it simple and clear!

I’m seeking a CSG implementation that can work live in-experience and keep flickering down to an absolute minimum

  1. What is the issue? Include screenshots / videos if possible!

The issue is even when I use a map that has been completed converted to all PartOperations via GeometryService and ONLY PartOperation:SubstituteGeometry() is used, the flickering is STILL present.

I’ve tried many different solutions thus far to try to get this to work, I understand that the technology may just really not be there yet for this sort of thing, but I think it’s just a little misleading to claim that the function circumvents flickering, when in reality it seems to start flickering at the same point as flickering would likely start if the service was being used on traditional BaseParts. (replacing via parent, etc)

Video: Watch RobloxStudioBeta_NwGlHzzrtE | Streamable

  1. What solutions have you tried so far? Did you look for solutions on the Developer Hub?

I’m not really sure what else to try, which is why I’m making this post. I’ll leave the code that utilizes SubstituteGeometry() below, all that you need to know for the map is it is entirely made up of PartOperations with MeshParts excluded of course. I can include that code if it is needed as well.

P.S - Just to be clear, it is 100% SubstituteGeometry() causing the flickering, removing the line of code inside of the for loop makes the flickering stop (which of course, results in no changes to the geometry.)

local mapConversionComplete : BoolValue = workspace:WaitForChild("MapConversionComplete");

print "waiting for the client map generation...";
repeat game:GetService("RunService").RenderStepped:Wait() until mapConversionComplete.Value;


local findBasePart : MeshPart = workspace.Model:FindFirstChild("leafPileMain", true);


local Player : Player = game:GetService("Players").LocalPlayer;
local GeometryService : GeometryService = game:GetService("GeometryService");

local p : RaycastParams =;
p.FilterDescendantsInstances = (workspace.Model:GetDescendants());
p.FilterType = Enum.RaycastFilterType.Include;

Player.Character:PivotTo(findBasePart.CFrame *, 50, 0));
print "GO TIME!"

while true do
	print "running!"
	local Block ="Part");
	Block.Anchored = true;
	Block.Material = Enum.Material.Grass;
	Block.Color = Color3.fromRGB(0, 0, 100);
	Block.Transparency = 1;
	-- // Get floor being stood on
	local r : RaycastResult = workspace:Raycast(Player.Character.HumanoidRootPart.Position +, 10, 0),, -1, 0).Unit * 5000, p);
	if (r) then
		if not (r.Instance:IsA("PartOperation")) then task.wait(1); continue; end;
		Block.CFrame = *, 40), -2,, 40));
		Block.Size =, 30, 30);
		local results : {PartOperation} = GeometryService:SubtractAsync(r.Instance, {Block}, {SplitApart = false});
		for i,v in pairs(results) do

having the same issue here, its still flickering :sob:
let me know if you found a solution to your problem

edit: also found out that it’s not flickering in their SimpleTools test place
edit 2: after trying for hours i finally got it working with no lag nor flickering



Thank you for replying, do you mind posting how you got it to stop flickering? I will mark your answer as the solution once you do.


Sure, here’s the code. I don’t really know how I got it working if I’m gonna be honest though :sob:

local options = {
	CollisionFidelity = Enum.CollisionFidelity.Default,
	RenderFidelity = Enum.RenderFidelity.Automatic,
	SplitApart = true,

    local newParts, errormessage = GeometryService:SubtractAsync(originalPart, {workspace.destroyPart}, options)
	if originalPart:IsA("PartOperation") then
		for i, v in newParts do
			v.Parent = originalPart.Parent
			v.CFrame = originalPart.CFrame
			v.Anchored = originalPart.Anchored
			v.UsePartColor = true
			v:SetAttribute("Destructible", true)
		originalPart.Parent = nil

(The original part is the mouse target I got from the client, it was a test for my game. Also use a debounce system on the original part so that the server or whatever actually gets time to render the new geometry things)

If you have any questions ask me.