Fixing this script that changes part to water

As the title states, how can I do this? The script below doesn’t work.

I need it to convert all the parts to the water (terrain block)

Script:

local folder = script.Parent

for i = 1, #folder:GetChildren() do
    local part = folder:GetChildren()[i]
    if part:IsA("BasePart") then
        game.Workspace.Terrain:FillBlock(part, part.Size, Enum.Material.Water)
    end
end

Workspace:
image

Can you please just confirm that it isn’t working correctly?

Looking at the code, the baseparts aren’t being removed so it is possible that the water is being spawned, but is hidden behind / within the parts.

1 Like

Can confirm it isn’t working properly.

I did change the code to remove the part after the parts were converted, here is the updated code:

local folder = script.Parent

for i = 1, #folder:GetChildren() do
	local part = folder:GetChildren()[i]
	if part:IsA("BasePart") then
		game.Workspace.Terrain:FillBlock(part, part.Size, Enum.Material.Water)
		part:Destroy()
	end
end

I ran the code in studio and found that it is actually erroring, “Unable to cast Instance to CoordinateFrame”.

The fix is fairly simple: simply replace the first parameter of FillBlock (part) with part.CFrame

i.e.

local folder = script.Parent
for i = 1, #folder:GetChildren() do
	local part = folder:GetChildren()[i]
	if part:IsA("BasePart") then
		game.Workspace.Terrain:FillBlock(part.CFrame, part.Size, Enum.Material.Water)
		part:Destroy()
	end
end

That did help, most of them convert, but the Is:A("BasePart") seems to be erroring so I’ll remove that and see if it loads faster.

I’ll mark it as the solution if I can do that myself.

Okay, so the issue is it won’t find all the parts and will only do about half of them.

I’ll run a few tests to see the issue

1 Like

After a few tests, it seems to still persist

Script didn’t change

Basically, a few parts convert straight away and then delete, but after that, it converts another half and then doesn’t delete those parts

And that’s the issue!

1 Like

you’re forgetting to add a third parameter to the for loop, that being 1

you could just do

for _,part in folder:GetChildren() do

end

but whatever

for i = 1, #folder:GetChildren(), 1 do
    local part = folder:GetChildren()[i]
    if part:IsA("BasePart") then
        game.Workspace.Terrain:FillBlock(part, part.Size, Enum.Material.Water)
    end
end
1 Like

It’s not just “whatever,” the bottom script literally calls :GetChildren for every part that it iterates

1 Like

I will mark this as the solution since it basically fixed it

The only other issue is that calling :Destroy() will break most of it, here is the final script I tinkered with to fix the issue:

local folder = script.Parent

for i = 1, #folder:GetChildren(), 1 do
	local part = folder:GetChildren()[i]
	if part:IsA("BasePart") then
		game.Workspace.Terrain:FillBlock(part.CFrame, part.Size, Enum.Material.Water)
	end
end

task.wait()
folder:Destroy()
1 Like

oh LMAO

yeahhh there’s a lot of better approaches for this, not my code though!

1 Like

Yes, because you’re calling :GetChildren every time you iterate, which is slow and ruins your script if any of the parts are destroyed

Using generalized iteration as @notsad2 suggested should fix that, although I still recommend only deleting the folder at the end of the script as that’ll be better than deleting all of the parts individually

local folder = script.Parent

for _, part in folder:GetChildren() do
	if part:IsA("BasePart") then
		workspace.Terrain:FillBlock(part.CFrame, part.Size, Enum.Material.Water)
	end
end

folder:Destroy()

Note that you can also use the workspace global instead of game.Workspace, and removing the task.wait at the end shouldn’t affect anything

3 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.