Placement generation system not working as intended

Alright, I don’t want to waste your time, so I’ll get straight to the point, I made a
system, in this system, a script loops through parts in a group of parts, it then
calculates a random position inside that part using a module script, and then ‘raycasts’ that object downward until it hits land. After that, it checks if the position is far enough away from all previously placed objects, and if so, it takes that ‘raycasted’ position, places an object there, and resizes it to a random size in between two numbers.

A diagram showing the system in action and how its intended to work can be seen here:




And the code demonstrating the system of events can be seen here:

Loop through each part in a group of parts-

while true do
	for i, region in pairs(workspace.RESOURCES:GetChildren()) do
		for i, regPrt in pairs(region:GetChildren()) do
			if regPrt.Name == "TreeSpawn" then
				if #region.Trees:GetChildren() <= region.Trees.MaxItems.Value then
-- it continues, but yeah, you get it

Module script that chooses a random position-

local ItemSpawning = {}

function ItemSpawning.Calculate(part)
	local random = Random.new()
	local randomCFrame = part.CFrame * CFrame.new(random:NextNumber(-part.Size.X/2,part.Size.X/2), random:NextNumber(-part.Size.Y/2,part.Size.Y/2), random:NextNumber(-part.Size.Z/2,part.Size.Z/2))
	return randomCFrame.Position
end


return ItemSpawning

Raycast down until land is detected-

local function castDownRay(center, rayDist, dowat, cpart)
	--print(class.." - "..center.Position.X, center.Position.Y, center.Position.Z)
	--local radi = nil
	--if cpart:FindFirstChild("Bark") ~= nil then
	--	radi = getGreaterAxis(cpart:FindFirstChild("Bark"))
	--elseif cpart:FindFirstChild("Rock") ~= nil then
	--	radi = getGreaterAxis(cpart:FindFirstChild("Rock"))
	--else	
	--	radi = getGreaterAxis(cpart:FindFirstChild("Center"))
	--end
	if dowat == false then
		raycastParams.IgnoreWater = false
		wParams.IgnoreWater = false
	elseif dowat == true then 
		raycastParams.IgnoreWater = true
		wParams.IgnoreWater = true
	end
	local cent = center * CFrame.new(0, 50, 0)
	local dist = center * CFrame.new(0, -500, 0)
	local og = workspace:Raycast(cent.Position, dist.Position, raycastParams)

	local pos = nil
	if og ~= nil --[[and #TRegHit > 0]] then
		if og.Material == Enum.Material.Water then
			pos = nil
		else
			--print(class.." - "..center.Position.X, og.Position.Y, center.Position.Z)
			pos = CFrame.new(center.Position.X, og.Position.Y, center.Position.Z)
		end
	end
	return pos 
end

Check if the position is far away from the pre-placed objects-

local function runcheckList(region, regPrt, deapos)
	local tocont = true
	for _, part in pairs(region.Trees:GetChildren()) do
		if part:IsA("NumberValue") or part:IsA("IntValue") or part:IsA("ObjectValue") then
		else
			if (Vector2.new(deapos.Position.X, deapos.Position.Z) - Vector2.new(part.PrimaryPart.Position.X, part.PrimaryPart.Position.Z)).Magnitude > 50 then
			else
				tocont = false
			end
		end
	end
	for _, part in pairs(region.Shrubs:GetChildren()) do
		if part:IsA("NumberValue") or part:IsA("IntValue") or part:IsA("ObjectValue") then
		else
			if (Vector2.new(deapos.Position.X, deapos.Position.Z) - Vector2.new(part.PrimaryPart.Position.X, part.PrimaryPart.Position.Z)).Magnitude > 17.5 then
			else
				tocont = false
			end
		end
	end
	for _, part in pairs(region.Rocks:GetChildren()) do
		if part:IsA("NumberValue") or part:IsA("IntValue") or part:IsA("ObjectValue") then
		else
			if (deapos.Position - part.PrimaryPart.Position).Magnitude > 27.5 then
			else
				tocont = false
			end
		end
	end
	for _, part in pairs(workspace.ANIMALS[region.Name]:GetChildren()) do
		if part:IsA("Model") then
			if part.PrimaryPart ~= nil  then
				if (deapos.Position - part.PrimaryPart.Position).Magnitude > ((part.PrimaryPart.X + part.PrimaryPart.Z + part.PrimaryPart.Y)/3) * 1.25 then
				else
					tocont = false
				end 
			end
		end
	end
	for _, part in next, workspace.CHARACTERS:GetChildren() do
		if (deapos.Position - part.PrimaryPart.Position).Magnitude > ((part.PrimaryPart.X + part.PrimaryPart.Z + part.PrimaryPart.Y)/3) * 1.25 then
		else
			tocont = false
		end
	end
	local box = regPrt
	local x, y, z = deapos.Position.X, deapos.Position.Y, deapos.Position.Z
	if x < box.Position.X + box.Size.x/2 and x > box.Position.X - box.Size.x/2 then
		--if y < box.Position.Y + box.Size.y/2 and y > box.Position.Y - box.Size.y/2 then
			if z < box.Position.Z + box.Size.z/2 and z > box.Position.Z - box.Size.z/2 then
			
			else
				tocont = false
			end
		--end
	else
		tocont = false
	end	
	return tocont
end

Resize and place object in position-

--print(class.." - "..(pos + Vector3.new(0, 10, 0)).X, (pos + Vector3.new(0, 10, 0)).Y, (pos + Vector3.new(0, 10, 0)).Z)
						local deapos = castDownRay(CFrame.new(pos + Vector3.new(0, 10, 0)), 350, region.Water.Value, region.Trees.Obj.Value)
						if deapos ~= nil then
							local tocont = runcheckList(region, regPrt, deapos)
							if tocont == true then
								deapos *= CFrame.new(0, -2.5, 0)
								local tempVar = nil
								if region.Trees:FindFirstChild("Obj2") ~= nil then
									if deapos.Position.Y < region.Trees.HeightDiff.Value then
										tempVar = region.Trees.Obj.Value:Clone()
									else
										tempVar = region.Trees.Obj2.Value:Clone()
									end		
								else
									tempVar = region.Trees.Obj.Value:Clone()
								end
								tempVar.Name = tempVar.Name
								local sizeVar = math.random(50, 145)/100
								scaleRig(sizeVar, tempVar)
								tempVar:PivotTo(deapos * CFrame.Angles(0, math.rad(math.random(1, 359)), 0))
								tempVar.Parent = region.Trees
								local wel = Instance.new("WeldConstraint", tempVar.PrimaryPart) 
								wel.Part0 = regPrt
								wel.Part1 = tempVar.PrimaryPart
								for i, v in pairs(tempVar:GetDescendants()) do
									if v:IsA("BasePart") or v:IsA("MeshPart") then
										v.Anchored = false
									end
								end
							end
						end

So yeah, I have a code to generate the objects, but you might be wondering well, what’s the problem, and of course, I wouldn’t be making a post if there was no problem. The problem is that the system places objects outside of its bound box, and when used in my main game, does not work right AT ALL, mostly because it places objects inside the terrain itself.

If there is something unclear in the scripts, or the post in general, please inform me, and if you see any flaws with the system itself aswell, I would love to hear how I can improve it.

Thanks for taking the time to read my post, and hopefully you can help me fix this problem :sweat:

2 Likes