How can I wait for parts to exist?

I have this plot system that loads players plots. And when it’s done that, it spawns the player in. However, I am having issues where even after the plot has supposedly fully loaded in and I even wait 7 whole seconds before spawning the character in, on occassion the player can spawn inside the ground.

What I do is, because players can build over their spawn, is I place their spawn in the sky, raycast vertically down until a block is found, then add 10 studs up, so player can spawn on top of block safely.

player.CharacterAdded:Connect(function(character)
	task.wait()
		
	-- Spawn player at spawn
	local Params = RaycastParams.new()
	Params.FilterDescendantsInstances = {PlotInfo.Plot}
	Params.FilterType = Enum.RaycastFilterType.Whitelist
	
	local NewRay = workspace:Raycast(
		PlotInfo.Plot.Spawn.Position,
		-PlotInfo.Plot.Spawn.CFrame.UpVector * 1000,
		Params
	)
	
	if NewRay then -- Part found, spawn there
		character:PivotTo(
			NewRay.Instance.CFrame + Vector3.new(0, 10, 0)
		)
	else -- No ray, just spawn at spawn part
		character:PivotTo(PlotInfo.Plot.Spawn.CFrame)
	end
end)
function PlotManager:Load()
	local PlayersPlotData = PlotData:GetAsync(self.Owner.UserId .. "-" .. self.PlotId)
	local BlockCount = 0
	if PlayersPlotData then -- Save exists, apply changes
		self.Plot.Blocks:ClearAllChildren() -- Remove all blocks from default Plot
		
		-- Collect all BlockData and create the blocks
		for x, xContents in pairs(PlayersPlotData) do
			for y, yContents in pairs(xContents) do
				for z, block in pairs(yContents) do
					local BlocksData, ExtraData, ExtraSlab, ExtraSlabData = self:Deserialize(block)
					if BlocksData then -- BlockData exists
						local BlockModel = Blocks:FindFirstChild(BlocksData.Name)
						if BlockModel then -- Get the blocks model
							self:CreateBlock(BlockModel, ExtraData, x, y, z)
							
							BlockCount += 1
						end
					end
					
					if ExtraSlab then -- Extra slab
						local BlockModel = Blocks:FindFirstChild(ExtraSlab.Name)
						if BlockModel then -- Get the blocks model
							self:CreateBlock(BlockModel, ExtraData, x, y, z)
							
							BlockCount += 1
						end
					end
				end
			end
		end
	end
	
	task.wait(7) -- Give plot time to fully be loaded in
	
	if not self.Owner or not self.Owner.Parent then return end -- Left
		
	CharacterManager.Load(self.Owner) -- Plot loaded, load in player
	
	self.PlotLoaded = true
end

As you can see, I get and create all the blocks in the for loop. Then once that’s done I wait a whole 7 seconds (I don’t want to do that but I find myself continously just adding more and more seconds into this wait cause of how long the blocks take to load)

As you can also see, I tried doing like a BlockCount, but that goes from 0 to 1982 (blocks in my plot) in a split second, so like I said, nothing in the for loop yields, and to my knowledge there should be no delay between a block being cloned and put into workspace

I would have thought once I create and parent a part to workspace, it’d be there instantly, but I don’t know why there’s such a large delay between them all being added when there’s no yielding involved.

I believe it’s replication lag, maybe you can have a “PartCount” IntValue and a localscript that waits until the number of parts is equal to the PartCount, and then it fires a remote event to spawn the player.

You can use WaitForChild, but if you are going to be using instance.new for the parts, you are going to have define the parent, name, and all that fun stuff.

Are you using Streaming?
I imagine that the plot position is variable - so perhaps your plot is being created outside of the Streaming area, spawn character and the instances are technically not rendered in yet.

You could try setting the Camera.Focus to the location of your plot.
Camera (roblox.com)

-edit-
Did you find a solution that worked?
@NinjaOnline?
If so, either mark the solution or write a reply with the solution, as some other developers may want to find a similar answer. =)