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