My placement system is Terrible!

  1. What do you want to achieve?
    I would like to be able to place blocks without having to actually put my mouse on a block. I would like it to be like bedwars where you can stand at the edge of a bridge and hover your mouse over the void to place a block which connects to your bridge.

  2. What is the issue?
    I can place blocks but I must click on another block to form a bridge. (Like build to survive). I would like to be able to place blocks like bedwars.

  3. What solutions have you tried so far? I simply have no idea where to begin to create this sort of system.

Is there some sort of formula I could use to make this happen? I would love to learn how to script something like this for future projects. Is the placement supposed to be based off the character?

Summary

This is what I have currently
image

Here I want to be able to place a block which connects to the bridge.
image

Code (Local Script)
local tool = script.Parent

local player = game.Players.LocalPlayer
local mouse = player:GetMouse()

local character = player.Character or player.CharacterAdded:Wait()
local range = 30
local userInputservice = game:GetService("UserInputService")
local runService = game:GetService("RunService")

local canPlace = false

local mousePosition = Vector3.new(0, 0, 0)

local replicatedStorage = game:GetService("ReplicatedStorage")
local blocks = replicatedStorage:WaitForChild("Blocks")
local currentBlock = blocks:FindFirstChild(script.Parent.Name)
local placingBlock = blocks:WaitForChild("Placing")

local newBlock

local function getMouse3dPosition(ignoreOne)
	local mouseRay = mouse.UnitRay
	local castRay = Ray.new(mouseRay.Origin, mouseRay.Direction * 1000)
	local ignoreList = {player.Character, tool, ignoreOne}
	
	local hit, position = workspace:FindPartOnRayWithIgnoreList(castRay, ignoreList)
	if hit and position then
		return position, hit
	end
end

tool.Equipped:Connect(function()
	canPlace = true
	if canPlace then
	
		newBlock = placingBlock:Clone()
		newBlock.Anchored = true
		newBlock.CanCollide = false
		newBlock.Parent = workspace
		while canPlace do
			wait()
			local newMousePosition, object = getMouse3dPosition(newBlock)
			mousePosition = newMousePosition
			
			if mousePosition then 
			
				local x, y, z = mousePosition.X, mousePosition.Y, mousePosition.Z
				if x and y and z then
					local vector3 = Vector3.new(math.round(x/2)*2, math.round(y/2)*2, math.round(z/2)*2)
					
					if (character.HumanoidRootPart.Position-vector3).Magnitude > range then
						--too far
					else
						newBlock.Position = vector3
					end
				end
			end
		end
	end
end)

tool.Unequipped:Connect(function()
	canPlace = false
	if newBlock then
		newBlock:Destroy()
	end
end)

tool.Activated:Connect(function()
	print("Activated	")
	if newBlock then
		local block = currentBlock:Clone()
		block.Position = newBlock.Position
		block.Anchored = true
		block.CanCollide = true
		block.Parent = workspace
	end
end)
2 Likes

I found this post but the script seems complicated. Can anyone help me to understand it?

Check if:

  • the ray hit nothing
  • the player is standing on a block
  • there’s no block in front of the player in the direction (HumanoidRootPart.LookVector) they’re facing

and then:

  • using the LookVector calculate where should the block be put (front, right, left)
  • place the block using the CFrame of the block the player is standing on + offset calculated using the direction

What if the wish to place a block farther away? For example:
image

Then, instead of checking if there’s no block in front of the player, get the furthest connected block in given direction.
You can get connected blocks using spatial queries.
This is how you could get the edge block, then you can do calculations using it.

1 Like