How to have efficient block creation that feels seemless

I’ve got a mine system, where when you break blocks, it creates new blocks around as needed. Having looked at other games with similar systems, they all just do block breaking on the server. While this does solve any issues of the block being destroyed before the other blocks are created, it leads to slow reaction times, and in these games it can take me 1-2 full seconds after I’ve ‘mined’ the block, for it to actually disappear. I wanted to destroy it on the client, so the client destroys it, while the server is also destroying it on server + creating blocks. However, this leads to you falling through the world, as the block is destroyed instantly, but the server hasn’t had time to generate new blocks.

DestroyBlock:FireServer(self.CurrentBlock)
	
	-- Do visuals of entity
	CreateEntity:Fire(
		self.CurrentBlock:GetAttribute("Id"),
		self.CurrentBlock.Position
	)
	
	if self.CurrentBlock:IsDescendantOf(Mine.Blocks) then -- Mine block, need to create blocks
		CreateMineBlock:Invoke(self.CurrentBlock)
	end

	self.CurrentBlock:Destroy()

On CreateMineBlock.OnInvoke

local function BlockRemoved(block)
	local BlockPosition = block.Position
	
	for _, facePosition in pairs(POSITIONS) do
		local NewPosition = BlockPosition + facePosition
		
		local RoundedY = math.floor(NewPosition.Y * 10) / 10
		local Position = Vector3.new(NewPosition.X, RoundedY, NewPosition.Z)
		
		if Position.Y > 0.5 then continue end -- Can't go above Y = 0
		
		-- Top levels
		if (Position.X < TOP_X.X or Position.X > TOP_X.Y) and Position.Y > TOP_MIN then continue end -- Can't go outside these bounds
		
		if (Position.Z < TOP_Z.X or Position.Z > TOP_Z.Y) and Position.Y > TOP_MIN then continue end -- Can't go outside these bounds
		
		-- Bottom levels
		if (Position.X < BOTTOM_X.X or Position.X > BOTTOM_X.Y) and Position.Y > BOTTOM_MIN then continue end -- Can't go outside these bounds
		
		if (Position.Z < BOTTOM_Z.X or Position.Z > BOTTOM_Z.Y) and Position.Y > BOTTOM_MIN then continue end -- Can't go outside these bounds
		
		local PreviouslyGenerated = false
		
		for _, generated in pairs(Mine.Blocks:GetChildren()) do
			if generated.Position == Position then -- Already generated
				PreviouslyGenerated = true
				
				break
			end
		end
		
		if PreviouslyGenerated then continue end -- Position already generated
		
		CreateBlock(Position)
	end
	
	return true
end

So the above will create temporary blocks on the client, while the server has time to place the real blocks

So, how can I successfully have the block destroyed, and create some ‘temp’ blocks on the client, while the server has time to create the real blocks? Or am I overthinking it, and should just stick with the latency :confused:

Tips:

  1. Create the bottom most block first before the sides, also parenting it first.
  2. Maybe anchor the HumanoidRootPart for a moment to avoid void fall.
  3. Sometimes you have to live with the latency because trying to use a hacky method to get around it might make things worse lol.

Hmmm, ye I might just stick with latency :confused: any tips on how to have the bottom block go first tho, if I’m just looping through vectors?

local POSITIONS = {
	Vector3.new(3, 0, 0),
	Vector3.new(-3, 0, 0),
	Vector3.new(0, 3, 0),
	Vector3.new(0, -3, 0),
	Vector3.new(0, 0, 3),
	Vector3.new(0, 0, -3),
}

I assume the order of these means nothing though

You could first compare which one has the lowest Y position before creating and placing the new blocks. Then create the block with the lowest Y and remove it from the table. Then loop through the table for the remaining positions.

local lowestY = 0
local indexToUse = 0
for i = 1, #POSITIONS do
	if POSITIONS[i].Y < lowestY then
		lowestY = POSITIONS[i].Y
		indexToUse = i
	end
end

then create this block first: POSITIONS[indexToUse]
then remove it from table: table.remove(POSITIONS, indexToUse)
then loop through remaining table contents like you normally would.

1 Like