Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

Why are these chunks still overwriting?!

Hi, so I have a script that gets plates (they're models, not parts) from ReplicatedStorage that I like to call "chunks". I'm trying to make them not overwrite each other by checking if another chunk has the same X and Z position as the new chunk and destroying the new one if so, but they still overlap each other.

Also, one chunk in the corner (relative to chunk "0", the chunk generated from) doesn't generate.

Script:

local storage = game:GetService("ReplicatedStorage")

function newChunk(id)
	local chunks = storage.ChunkTypes:GetChildren()
	if id == 1 then
		local newPos = Vector3.new(script.Parent.Position.X + 256, 
			script.Parent.Position.Y, 
			script.Parent.Position.Z
		)
		local chunkTypes = storage.ChunkTypes:GetChildren()
		local newChunk = chunkTypes[math.random(1,#chunkTypes)]:Clone()
		for _, each in ipairs(workspace.Chunks:GetChildren()) do
			if each.Base.Position == newPos then
				newChunk:Destroy()
			else
				newChunk.Parent = workspace.Chunks; newChunk.Name = newChunk.Name..workspace.NextChunk.Value; newChunk:MoveTo(newPos)
			end
		end
	elseif id == 2 then
		local newPos = Vector3.new(script.Parent.Position.X - 256, 
			script.Parent.Position.Y, 
			script.Parent.Position.Z
		)
		local chunkTypes = storage.ChunkTypes:GetChildren()
		local newChunk = chunkTypes[math.random(1,#chunkTypes)]:Clone()
		for _, each in ipairs(workspace.Chunks:GetChildren()) do
			if each.Base.Position == newPos then
				newChunk:Destroy()
			else
				newChunk.Parent = workspace.Chunks; newChunk.Name = newChunk.Name..workspace.NextChunk.Value; newChunk:MoveTo(newPos)
			end
		end
	elseif id == 3 then
		local newPos = Vector3.new(script.Parent.Position.X, 
			script.Parent.Position.Y, 
			script.Parent.Position.Z + 256
		)
		local chunkTypes = storage.ChunkTypes:GetChildren()
		local newChunk = chunkTypes[math.random(1,#chunkTypes)]:Clone()
		for _, each in ipairs(workspace.Chunks:GetChildren()) do
			if each.Base.Position == newPos then
				newChunk:Destroy()
			else
				newChunk.Parent = workspace.Chunks; newChunk.Name = newChunk.Name..workspace.NextChunk.Value; newChunk:MoveTo(newPos)
			end
		end
	elseif id == 4 then
		local newPos = Vector3.new(script.Parent.Position.X, 
			script.Parent.Position.Y, 
			script.Parent.Position.Z - 256
		)
		local chunkTypes = storage.ChunkTypes:GetChildren()
		local newChunk = chunkTypes[math.random(1,#chunkTypes)]:Clone()
		for _, each in ipairs(workspace.Chunks:GetChildren()) do
			if each.Base.Position == newPos then
				newChunk:Destroy()
			else
				newChunk.Parent = workspace.Chunks; newChunk.Name = newChunk.Name..workspace.NextChunk.Value; newChunk:MoveTo(newPos)
			end
		end
	elseif id == 5 then
		local newPos = Vector3.new(script.Parent.Position.X + 256, 
			script.Parent.Position.Y, 
			script.Parent.Position.Z + 256
		)
		
	elseif id == 6 then
		local newPos = Vector3.new(script.Parent.Position.X - 256, 
			script.Parent.Position.Y, 
			script.Parent.Position.Z - 256
		)
		local chunkTypes = storage.ChunkTypes:GetChildren()
		local newChunk = chunkTypes[math.random(1,#chunkTypes)]:Clone()
		for _, each in ipairs(workspace.Chunks:GetChildren()) do
			if each.Base.Position == newPos then
				newChunk:Destroy()
			else
				newChunk.Parent = workspace.Chunks; newChunk.Name = newChunk.Name..workspace.NextChunk.Value; newChunk:MoveTo(newPos)
			end
		end
	elseif id == 7 then
		local newPos = Vector3.new(script.Parent.Position.X + 256, 
			script.Parent.Position.Y, 
			script.Parent.Position.Z - 256
		)
		local chunkTypes = storage.ChunkTypes:GetChildren()
		local newChunk = chunkTypes[math.random(1,#chunkTypes)]:Clone()
		for _, each in ipairs(workspace.Chunks:GetChildren()) do
			if each.Base.Position == newPos then
				newChunk:Destroy()
			else
				newChunk.Parent = workspace.Chunks; newChunk.Name = newChunk.Name..workspace.NextChunk.Value; newChunk:MoveTo(newPos)
			end
		end
	elseif id == 8 then
		local newPos = Vector3.new(script.Parent.Position.X - 256, 
			script.Parent.Position.Y, 
			script.Parent.Position.Z + 256
		)
		local chunkTypes = storage.ChunkTypes:GetChildren()
		local newChunk = chunkTypes[math.random(1,#chunkTypes)]:Clone()
		for _, each in ipairs(workspace.Chunks:GetChildren()) do
			if each.Base.Position == newPos then
				newChunk:Destroy()
			else
				newChunk.Parent = workspace.Chunks; newChunk.Name = newChunk.Name..workspace.NextChunk.Value; newChunk:MoveTo(newPos)
			end
		end
	end
end

script.Parent.Touched:connect(function(h)
	if game.Players:GetPlayerFromCharacter(h.Parent) then
		for i = 1,8 do
			newChunk(i)
		end
		workspace.NextChunk.Value = workspace.NextChunk.Value + 1
		script:Destroy()
	end
end)

It may seem kinda big, but if you help me, you get a free figurative, nonexistent cookie.

Help, please?

1 answer

✓ Accepted answer

You see how each id has nearly identical code? That's a sign you should be using tables and/or functions:

--The only difference between each block is the position, which you generate from the id, so make that an argument. You don't use the id elsewhere, so we'll omit that.
function newChunk(relPos) -- relPos is "relative position" (compared to script position)
	local newPos = script.Parent.Position + relPos
	--Check to see if a chunk already exists and return early if it does
        for _, each in ipairs(workspace.Chunks:GetChildren()) do
            if each.Base.Position == newPos then
                return
            end
	end
	-- Now we can create the chunk
        local chunkTypes = storage.ChunkTypes:GetChildren()
        local newChunk = chunkTypes[math.random(1,#chunkTypes)]:Clone()
        newChunk.Name = newChunk.Name..workspace.NextChunk.Value
	newChunk:MoveTo(newPos)
        newChunk.Parent = workspace.Chunks -- do as much as you can before parenting to minimize lag; especially MoveTo
end
--Now you could still have the "if id == 1 then newChunk(Vector3.new(256, 0, 0)) elseif id == 2 then ...", or you could use this table to convert from id to Vector3:
local pos = {
	Vector3.new(256, 0, 0),
	Vector3.new(-256, 0, 0),
	Vector3.new(0, 0, 256),
	--TODO finish
}
--Now the final part of your script:
script.Parent.Touched:connect(function(h)
    if game.Players:GetPlayerFromCharacter(h.Parent) then
        for i = 1,8 do
            newChunk(pos[i])
        end
        workspace.NextChunk.Value = workspace.NextChunk.Value + 1
        script:Destroy()
    end
end)

I'm sure you can imagine the benefit of only having to change your code in one place, rather than 8. If you mean to have more than 8 chunks, you should look into understanding tables better so that you can manage any number of chunks in a 2D table:

chunks = {}
local function GetChunkRow(x)
	local c = chunks[x]
	if not c then
		c = {}
		chunks[x] = c
	end
	return c
end
local function GetChunk(x, z)
	return GetChunkRow(x)[z]
end
local function SetChunk(x, z, value)
	GetChunkRow(x)[z] = value
end
--Whether x and z should be the center of each chunk or some other coordinate system is for you to decide. Example usage:
if not GetChunk(256, 0) then
	local newChunk = createNewChunkHere
	SetChunk(256, 0, newChunk)
end

As for the problem you're encountering, one possibility is that :MoveTo isn't putting the model exactly where you want it. If each chunk model has a PrimaryPart (or if you can set one), you can then use SetPrimaryPartCFrame which will guarantee that the primary part is at the exactly correct position. Alternatively, if you use the table system with GetChunk/SetChunk I just showed, it should also work since you won't be relying on .Position.

1 comment

0

Thank you :)

This discussion is preserved as it was. New answers, comments, and votes are closed.