No I’m pretty sure PreciseConvexDecomposition means that when you have consistent holes in a flate brick that you can pass through them. Look I’m not building a castle here with floor unions. I’ve generated a simple flat brick union then I add holes to it. This object is simple it works for most of the holes then it randomly doesn’t work. My algorithm to merge overlapping floor unions is super efficient. It does it in two main steps. It’s like a chain of checking a part and the parts that it overlaps with those and the parts they overlap with. While not doing it unnessarily. I’d be happy to share the source code if you think that’s useful enough to use.
local CollectionService = game:GetService("CollectionService")
local num=0
-- Function to create a new part and handle unions
local function getinterest(types)
if types==true or types==nil then
local newpayload={}
for i,v in CollectionService:GetTagged("floorunion") do
if v:HasTag("omit") then
else
table.insert(newpayload,v)
end
end
return newpayload
else
return CollectionService:GetTagged(types)
--return workspace:GetChildren()
end
end
local materials={
Enum.Material.WoodPlanks,Enum.Material.Asphalt,Enum.Material.Limestone,Enum.Material.Concrete,Enum.Material.CrackedLava,Enum.Material.Cobblestone,Enum.Material.Pavement,Enum.Material.Glacier,Enum.Material.Marble,Enum.Material.Metal,Enum.Material.Brick,Enum.Material.CeramicTiles,
}
local materialColors = {
[Enum.Material.WoodPlanks] = Color3.fromRGB(139, 69, 19), -- Brown
[Enum.Material.Asphalt] = Color3.fromRGB(50, 50, 50), -- Dark Gray
[Enum.Material.Limestone] = Color3.fromRGB(200, 200, 169), -- Light Beige
[Enum.Material.Concrete] = Color3.fromRGB(128, 128, 128), -- Gray
[Enum.Material.CrackedLava] = Color3.fromRGB(207, 16, 32), -- Red
[Enum.Material.Cobblestone] = Color3.fromRGB(112, 128, 144), -- Slate Gray
[Enum.Material.Pavement] = Color3.fromRGB(105, 105, 105), -- Dim Gray
[Enum.Material.Glacier] = Color3.fromRGB(173, 216, 230), -- Light Blue
[Enum.Material.Marble] = Color3.fromRGB(255, 255, 255), -- White
[Enum.Material.Metal] = Color3.fromRGB(169, 169, 169), -- Silver
[Enum.Material.Brick] = Color3.fromRGB(178, 34, 34), -- Brick Red
[Enum.Material.CeramicTiles] = Color3.fromRGB(255, 255, 255), -- White
}
--materialColors[Enum.Material.WoodPlanks].
local function applyNoiseToColor(color)
local function clamp(value, min, max)
if value < min then
return min
elseif value > max then
return max
else
return value
end
end
local r = clamp(color.R * 255 + math.random(-25, 25), 0, 255)
local g = clamp(color.G * 255 + math.random(-25, 25), 0, 255)
local b = clamp(color.B * 255 + math.random(-25, 25), 0, 255)
return Color3.fromRGB(r, g, b)
end
local amnt=#materials
local debris=game:GetService("Debris")
--local globalpayload={}
local function areObjectsOverlapping(object1,key)
-- Get the CFrame and size of the first object
local cframe1 = object1.CFrame
local size1 = object1.Size
-- Create OverlapParams
local overlapParams = OverlapParams.new()
overlapParams.FilterType = Enum.RaycastFilterType.Include
overlapParams.FilterDescendantsInstances = getinterest(key or true)
if key=="stairunion" then
overlapParams.BruteForceAllSlow=true
end
local overlappingParts = workspace:GetPartBoundsInBox(object1.CFrame,object1.Size+Vector3.new(5,2,5), overlapParams)
local payload={}
if key=="stairunion" then
--print(overlappingParts)
local maxr=math.max(object1.Size.X,object1.Size.Z)
for i,v in overlappingParts do
if math.abs(v.Position.Y-object1.Position.Y)<2 then
if (v.Position-object1.Position).Magnitude<maxr then
table.insert(payload,v)
end
end
end
return payload
end
--local long=math.max(object1.Size.X,object1.Size.Z)*.5
for i,v in overlappingParts do
if (v.Position.Y==object1.Position.Y) and v~=object1 then
if v:IsA("BasePart") and (v.Size.X<=object1.Size.X and v.Size.Z<=object1.Size.Z) and v.Position==object1.Position then--or not v:IsDescendantOf(workspace) then
v:RemoveTag("floorunion")
v.Parent=nil
v:Destroy()
else--if (v.Position-object1.Position).Magnitude<(math.max(v.Size.X,v.Size.Z)*.5)+long then
table.insert(payload,v)
end
end
end
return payload
end
function module.createFloorUnion(cframe, size,texture,noterrain)
-- Create the new part
local newPart = Instance.new("Part")
newPart.CFrame = cframe
newPart.Size = size
newPart.Anchored = true
newPart.Parent = workspace
newPart.Name="floorunion"..num
newPart:AddTag("terraincheck")
num+=1
areObjectsOverlapping(newPart)
--local newPart=getpayload(newPart)
local number=num
CollectionService:AddTag(newPart, "floorunion")
newPart.Name="floorunion"..number
--num+=1
newPart.Material=materials[math.random(1,amnt)]
if typeof(texture)=="table" then texture=texture[1] end
if texture then texture:Clone().Parent=newPart end
newPart.Color=applyNoiseToColor(materialColors[newPart.Material])--Color3.fromRGB(r,g,b)
newPart.Material=materials[math.random(1,amnt)]
newPart.CastShadow=false
local v=newPart
--if noterrain==nil or noterrain==false then
-- if v:HasTag("terraincheck") then
-- v:RemoveTag("terraincheck")
-- workspace.Terrain:FillBlock(v.CFrame:ToWorldSpace(CFrame.new(0,10,0)),Vector3.new(v.Size.X+4,24,v.Size.Z+4),Enum.Material.Air)
-- v:AddTag("terraincheck2")
-- elseif v:HasTag("terraincheck2") then
-- v:RemoveTag("terraincheck2")
-- v:AddTag("terraincheck3")
-- elseif v:HasTag("terraincheck3") then
-- v:RemoveTag("terraincheck3")
-- workspace.Terrain:FillBlock(v.CFrame:ToWorldSpace(CFrame.new(0,10,0)),Vector3.new(v.Size.X+4,24,v.Size.Z+4),Enum.Material.Air)
-- end
-- end
-- end
end
local processing=script.Signal
local function mergepayload(payload,newPart,texture,stairs)
if #payload>=1 and newPart and newPart.Parent then
-- print(payload)
pcall(function() texture.Parent=nil end)
if stairs==nil then
for i,v in payload do
if v.Parent==nil or newPart.Position.Y~=v.Position.Y then
table.remove(payload,i)
end
end
end
if #payload>=1 then
local union
if stairs==nil then
union=newPart:UnionAsync(payload,Enum.CollisionFidelity.PreciseConvexDecomposition)
else
union=newPart:SubtractAsync(payload,Enum.CollisionFidelity.PreciseConvexDecomposition)
end
union.Parent=workspace
if texture then
pcall(function() texture.Parent=union end)
end
-- union.UsePa
if stairs==nil then
for i,v in payload do
v:RemoveTag("floorunion")
v.Parent=nil
v:Destroy()
debris:AddItem(v,.01)
end
else
for i,v in payload do
debris:AddItem(v,15)
end
end
--CollectionService:AddTag(union, "floorunion")
union.Name=newPart.Name
union.Material=materials[math.random(1,amnt)]
union.Color=applyNoiseToColor(materialColors[union.Material])--Color3.fromRGB(r,g,b)
union.UsePartColor=true
newPart:RemoveTag("floorunion")
newPart.Parent=nil
newPart:Destroy() debris:AddItem(newPart,0.01)
--if not stairs then
union:AddTag("floorunion")
--end
--print("Merged")
else
newPart:AddTag("floorunion")
end
else
end
end
local function mergeobjects()
local array=getinterest(true)
local payload={}
local function recursiveoverlap(i,t)
local overlaps=areObjectsOverlapping(t)
if #overlaps>0 then
for r,v in overlaps do
--if v:HasTag("floorunion" then
if v:HasTag("floorunion") then
v:RemoveTag("floorunion")
--recursiveoverlap(i,v)
table.insert(payload[i].Parts,v)
end
end
for r,v in overlaps do
--v:RemoveTag("floorunion")
recursiveoverlap(i,v)
--table.insert(payload[i].Parts,v)
end
end
end
for i,v in array do
if v:HasTag("floorunion") and v.Size.X<1024 and v.Size.Z<1024 then
v:RemoveTag("floorunion")
if payload[i]==nil then
payload[i]={Union=v,Parts={}}
end
for r,t in areObjectsOverlapping(v) do
if i~=r and t:HasTag("floorunion") then
t:RemoveTag("floorunion")
table.insert(payload[i].Parts,t)
recursiveoverlap(i,t)
end
end
if #payload[i].Parts==0 then
payload[i]=nil
end
v:AddTag("floorunion")
end
end
return payload
end
local function mergestairunion()
local array=getinterest(true)
local payload={}
local function recursiveoverlap(i,t)
local overlaps=areObjectsOverlapping(t,"stairunion")
if #overlaps>0 then
for r,v in overlaps do
--v:RemoveTag("floorunion")
--recursiveoverlap(i,v)
table.insert(payload[i].Parts,v)
end
--for r,v in overlaps do
-- --v:RemoveTag("floorunion")
-- recursiveoverlap(i,v)
----table.insert(payload[i].Parts,v)
--end
end
end
for i,v in array do
if payload[i]==nil then
payload[i]={Union=v,Parts={}}
end
for r,t in areObjectsOverlapping(v,"stairunion") do
table.insert(payload[i].Parts,t)
--recursiveoverlap(i,t)
end
if #payload[i].Parts==0 then
payload[i]=nil
end
end
return payload
end
local function MergeAll()
local payload=mergeobjects()
for i,v in payload do
mergepayload(v.Parts,v.Union,v.Union:FindFirstChildOfClass("Texture"))
end
local payload=mergestairunion()
for i,v in payload do
mergepayload(v.Parts,v.Union,v.Union:FindFirstChildOfClass("Texture"),true)
end
end
function module.ClearTerrain()
for i,v in getinterest() do
if v:HasTag("terraincheck") then
v:RemoveTag("terraincheck")
workspace.Terrain:FillBlock(v.CFrame:ToWorldSpace(CFrame.new(0,10,0)),Vector3.new(v.Size.X+4,24,v.Size.Z+4),Enum.Material.Air)
v:AddTag("terraincheck2")
elseif v:HasTag("terraincheck2") then
v:RemoveTag("terraincheck2")
workspace.Terrain:FillBlock(v.CFrame:ToWorldSpace(CFrame.new(0,10,0)),Vector3.new(v.Size.X+4,24,v.Size.Z+4),Enum.Material.Air)
v:AddTag("terraincheck3")
elseif v:HasTag("terraincheck3") then
v:RemoveTag("terraincheck3")
v:AddTag("terraincheck4")
workspace.Terrain:FillBlock(v.CFrame:ToWorldSpace(CFrame.new(0,10,0)),Vector3.new(v.Size.X+4,24,v.Size.Z+4),Enum.Material.Air)
elseif v:HasTag("terraincheck4") then
v:RemoveTag("terraincheck4")
workspace.Terrain:FillBlock(v.CFrame:ToWorldSpace(CFrame.new(0,10,0)),Vector3.new(v.Size.X+4,24,v.Size.Z+4),Enum.Material.Air)
end
end
end
function module.mergeStairUnions()
MergeAll()
processing.Value=false
end```