While loop within for loop not breaking

So I’m making a block generator, and I use perlin noise on the top layer for height variation. My strategy for filling in the holes is to check 1 block down for any blocks and if there isn’t, fill the hole and check again 1 block lower, however despite another block being successfully detected, the while loop seems to just keep going and spawning more blocks underneath. What do I do?

for i,v in pairs(topLayerParts) do
	local noBlock = true
	local block = v
	while noBlock and block do
		--print(noBlock)
		newPart = block:Clone()
		newPart.Position -= Vector3.new(0,newPart.Size.Y,0)
		newPart.Parent = game.Workspace
		wait()
		for k,j in pairs(newPart:GetTouchingParts()) do
			--print(j.Position, newPart.Position)
			if j:IsA("BasePart") and j.Position == newPart.Position then
				newPart:Destroy()
				noBlock = false
				block = nil
				break
			end
		end
		if not noBlock then break end
		block = newPart
	end
end
1 Like

About this:

sometimes comparing two Vector3 does not return false even if they are the same because
Vector3 is a very precised and sometimes the deffirence between two of them is just 0.00001 or smaller so comparing them will return false, try replace this with:

(j.Position - newPart.Position).Magnitude < 0.001

I think this should be reset to v rather than newPart.

block = newPart;

Should be

block = v

The positions are automatically rounded to a grid and again I have confirmed it does detect the other block and confirm it’s in the same location the only issue is that it continues spawning blocks indefinitely despite the conditions for the while loop to run are not supposed to be met

If I reset it to v, it will just check the same location over and over rather than building off previous work

A few things I have noticed with your code, and what is likely going to be a better method for you additionally included:

  1. To start with, the conditions of your loop are not particularly sound from my observations. When your first loop is made here:
if j:IsA("BasePart") and j.Position == newPart.Position then
	newPart:Destroy()
	noBlock = false
	block = nil
	break
end

If you haven’t realised however, you’ve asked if any parts are colliding but lets say theoretically no parts are colliding (because you’ve got it perfectly distanced away) - you can never actually reach this statement.

That being said however, if parts are colliding then the part must be perfectly placed in order to satisfy your logic. I’m not sure what your intended effect with this code is - however whilst the logic seems sound in areas it also seems quite generically flawed.

One thing I will say however is that Perlin Noise has distinct principles:
This means when we program it, we should already know the maximum allowed height as generically the whole point of using this perlin noise is that we wish to create a smooth generated landscape. If we already know what the maximum height of the block can possibly be, we could easily use this information to create a smooth surface.

I think this code by @Operatik, highlights perfectly what Perlin Noise can do as its all bound by maths:

local xScale = 30
local zScale = 30
local height = 20
 
local noise = math.noise
local t = workspace.Terrain
local setCell = t.SetCell
local clear = t.Clear
 
for seed = 0,10,0.01 do
    clear(t)
    for x = -30,30 do
        for z = -30,30 do
            local y = noise(seed,x/xScale,z/zScale) * height
            setCell(t,x,y,z,1,0,0)
            setCell(t,x,y-1,z,1,0,0)
        end
    end
    wait()
end

The gaps it’s trying to fill are underneath the blocks as the perlin layer is above other flat layers
Also, for the second time, I have confirmed that it does SUCCESSFULLY detect blocks when it creates a block within another, but the while loop doesn’t stop running

Stop trying to change the subject

Yeah I hear you, I got it working down to two blocks thick but after that it doesn’t infill the gaps. I think the problem is down to the touched event, and the order in which the conditions are being checked and set/reset.

I’ve given up Roblox just refuses to act normal

if j:IsA("BasePart") and (j.Position - newPart.Position).Magnitude < 0.001 then