YES!
This will make so many things possible!
I’m excited to try it!
YES!
This will make so many things possible!
I’m excited to try it!
y e s
I must say, I felt really negated without this feature. I’m glad you guys unioned up to create something so awesome!
Seriously though, I remember a few years ago when something like this was unthinkable with CSG.
This update is much appreciated and will definitely be very helpful with making games feel more realistic.
WOO! Finally! This is going to be a game changer, I just hope it’s very optimised on a larger scale. If not, that’s perfectly fine.
Here’s a code sample that I wrote for in-game CSG a few weeks ago.
It makes explosions carve spheres out of nearby parts!
----------------------------------------------------------------------------------------------
-- @CloneTrooper1019, 2018 <3
-- SwissCheese.lua
----------------------------------------------------------------------------------------------
local function createRegion3FromPart(part)
local pos = part.Position
local size = part.Size
local corner0 = pos - (size/2)
local corner1 = pos + (size/2)
return Region3.new(corner0, corner1)
end
local function onExplosion(explosion)
-- Ignore visual-only explosions
if explosion.BlastPressure == 0 then
return
end
-- Create the sphere that will be subtracted with this explosion.
local radius = explosion.BlastRadius
local negateSphere = Instance.new("Part")
negateSphere.CFrame = CFrame.new(explosion.Position)
negateSphere.Size = Vector3.new(radius, radius, radius)
negateSphere.Shape = "Ball"
-- Cast negateSphere into the 'Objects' type.
local subtractor = {negateSphere}
-- Capture the parts within a Region3 formed by the sphere.
local region = createRegion3FromPart(negateSphere)
local parts = workspace:FindPartsInRegion3(region)
for _,part in pairs(parts) do
local success, result = pcall(function ()
return part:SubtractAsync(subtractor)
end)
if success then
-- Move the children of the old part into the new part.
for _,child in pairs(part:GetChildren()) do
child.Parent = result
end
-- Swap out the part with the union.
result.Parent = part.Parent
result.CFrame = part.CFrame
part:Destroy()
else
warn("SubtractAsync failed because:", result)
end
end
end
-- Listen for explosions being added to the workspace
local function onDescendantAdded(desc)
if desc:IsA("Explosion") then
onExplosion(desc)
end
end
workspace.DescendantAdded:Connect(onDescendantAdded)
----------------------------------------------------------------------------------------------
How often does real time CSG error compared to CSG in studio?
I’ve been wanting something like this for years. Thanks for the early release.
A developer @Lauri9 (view roblox profile) has worked on a quick demo, using this, which took only 3 hours(!!) to code and the results are promising!
AMAZING, I can’t wait to see what people do with this.
ive literally just made my entire map destructible i thank you
This is awesome!
What prevents this from being done on the client? The current solver is really fast and has little errors, especially compared to the old solver. This would reduce the network usage, and load much faster on the client.
Wrote a script that replicates the fragmenting parts shown off at RDC.
The secret is recursive plane cuts.
local fragmentPart = Instance.new("BindableEvent")
local tau = math.pi * 2
local function rollAngles(count)
local result = {}
for i = 1,count do
result[i] = math.random() * tau
end
return unpack(result)
end
local function subtract(part, negativePart, collisionFidelity)
if part:IsDescendantOf(workspace) then
local subtractor = {negativePart}
return part:SubtractAsync(subtractor, collisionFidelity)
end
end
local function onFragmentPart(part, depth)
if not part:IsDescendantOf(workspace) then
return
end
local depth = depth or 0
if depth > 4 then
return
end
local size = part.Size
if size.X < 1 or size.Y < 1 or size.Z < 1 then
return
end
local magnitude = size.Magnitude
if magnitude < 6 then
return
end
local cf = part.CFrame
local rx,ry,rz = rollAngles(3)
local cutPlane = cf * CFrame.Angles(rx, ry, rz)
local cut0 = Instance.new("Part")
cut0.Size = size*4
cut0.CFrame = cutPlane * CFrame.new(0,-size.Y*2,0)
local cut1 = cut0:Clone()
cut1.CFrame = cutPlane * CFrame.new(0,size.Y*2,0)
local part0, part1
pcall(function ()
part0 = subtract(part, cut0, "Hull")
part1 = subtract(part, cut1, "Hull")
end)
if part0 and part1 then
local parent = part.Parent
local velocity = part.Velocity
local rotVel = part.RotVelocity
part:Destroy()
local c0 = cf:toObjectSpace(part0.CFrame)
part0.CFrame = part.CFrame * c0
part0.Velocity = velocity
part0.RotVelocity = rotVel
part0.Parent = parent
local c1 = cf:toObjectSpace(part1.CFrame)
part1.CFrame = part.CFrame * c1
part1.Velocity = velocity
part1.RotVelocity = rotVel
part1.Parent = parent
-- Recursively fragment
fragmentPart:Fire(part0, depth+1)
fragmentPart:Fire(part1, depth+1)
end
end
local function onDescendantAdded(desc)
if desc:IsA("Explosion") then
local hasHit = {}
local function onExplosionHit(hit)
if not (hasHit[hit] or hit.Anchored or hit:FindFirstChildWhichIsA("FileMesh")) then
hasHit[hit] = true
fragmentPart:Fire(hit)
end
end
local hitSignal = desc.Hit:Connect(onExplosionHit)
delay(3,function ()
-- Garbage collect after the explosion is gone.
hitSignal:Disconnect()
hasHit = nil
end)
end
end
fragmentPart.Event:Connect(onFragmentPart)
workspace.DescendantAdded:Connect(onDescendantAdded)
Been playing with this and made a sword that slices parts.
Hiya - I keep receiving an error code 21 when testing CSG.
Here’s the test place.
Error Code 21 - CSG.rbxl (13.7 KB)
You’re creating the part on the client, which you’re passing to the server via remote. Since this part is created by the client, it isn’t replicated and the server just sees nil.
Instead of passing the part to the server, just pass the position where the player clicked and create the part on the server.
Pew pew pew! Unfortunately, the polygon count is excessive even for simple shapes. Those four little dents maxed out on the triangle limit.
Try using cylinders?