How to make a part parallel with the ground?

So I am making a game that generates a random terrain map using perlin noise and I am now trying to add chests generating but I run into the problem of, when the chests are on a hill, they stick out rather than being flat on the floor.

Example of the issue:
image
If the image is hard to understand, basically the ground is a declining hill but the chest has generated to be sticking out rather than being parallel with it. I was wondering if I could use raycasting or something to make it parallel with the ground. Any suggestions would be nice!

Here is the script that generates the world (The tree and chest in ServerStorage are just parts):

local size = Vector3.new(8,8,8)

local seed = math.random(1, 10e6)
local frequency = 3
local power = 32
local resolution = 200

local Parts = {}
for x = 1, resolution do  
	for z = 1, resolution do
		local y1 = math.noise(
			(x*frequency)/resolution,
			(z*frequency)/resolution,
			seed
		)

		local y2 = math.noise(
			(x*frequency*.125)/resolution,
			(z*frequency*.125)/resolution,
			seed
		)

		local y3 = math.noise(
			(x*frequency*4)/resolution,
			(z*frequency*4)/resolution,
			seed
		)
		
		local y = (y1*y2*power*power)+y3
		
		if y > -3 then
			game.Workspace.Terrain:FillBall(Vector3.new(x * size.X, y, z * size.Z), size.X, Enum.Material.Grass)
		else
			game.Workspace.Terrain:FillBall(Vector3.new(x * size.X, y, z * size.Z), size.X, Enum.Material.Sand)
		end
		
		local SpawnChance = math.random(1, 100)
		
		if SpawnChance > 99 then
			local SpawnLocation = game.ServerStorage.SpawnLocation:Clone()
			SpawnLocation.Position = Vector3.new(x * size.X, y + size.Y/2, z * size.Z) 
			SpawnLocation.Parent = game.Workspace
		end
		
		local chestConstant = 7500
		local chestThreshold = .1
		
		local ChestChance = math.noise(x * frequency * chestConstant / resolution, z * frequency * chestConstant / resolution, seed)
		
		if ChestChance > chestThreshold then
			local ChestNum = math.random(1,300)
			local ChestSpawnChance = 295
			
			if ChestNum > ChestSpawnChance then
				local Chest = game.ServerStorage.Chest:Clone()
				local ChestHeight = Chest.Size.Y
				local PartHeight = size.Y

				local ChestY = y + ((ChestHeight / 2) * PartHeight)

				if ChestY - (ChestY/2) <= 0 then
					Chest:Destroy()
				else
					Chest.Position = Vector3.new((x * size.X) + math.random(-size.X/2, size.X/2), ChestY, (z * size.Z) + math.random(-size.Z/2, size.Z/2))
					Chest.Orientation = Vector3.new(0,math.random(0,360),0)
					Chest.Parent = workspace
				end
			end
		end
		
		local c = 5 -- c is some constant you use to customise how the noise feels
		local threshold = 0.1 -- the TreeChance needs to be greater than this to spawn a tree

		local TreeChance = math.noise(x * frequency * c / resolution, z * frequency * c / resolution, seed)

		if TreeChance > threshold then
			local TreeNum = math.random(1,100)
			local TreeSpawnChance = 95
			
			if TreeNum > TreeSpawnChance then
				local Tree = game.ServerStorage.Tree:Clone()
				local TreeHeight = Tree.Size.Y
				local PartHeight = size.Y

				local TreeY = y + PartHeight / 2 + TreeHeight  / 2
				
				if TreeY - (TreeY/2) <= 0 then
					Tree:Destroy()
				else
					-- I changed it to Tree.Position instead of Tree.CFrame because the tree is a cylinder, so would spawn flat if I updated the CFrame instead of the position.
					Tree.Position = Vector3.new((x * size.X) + math.random(-size.X/2, size.X/2), TreeY, (z * size.Z) + math.random(-size.Z/2, size.Z/2))
					Tree.Orientation = Vector3.new(0,math.random(0,360),0)
					Tree.Parent = workspace
				end

			end
		end

	end
end
print("World has finished generating")

Maybe use raycasting to cast a ray downwards then use the point it touches in a CFrame.lookAt?

1 Like

you would have to use raycast then check the normal of the raycast then rotate accordingly