Need help with building system

Hello, I have been trying to code a placement system. It works, however I do not like how it works if that makes sense. My Preview placement part keeps going inside other blocks, and I just want to to be a nice smooth placement, similar to games like Minecraft or The Chosen One - Roblox

My Script:


local Tool = script.Parent
local TweenService = game:GetService("TweenService")
local Players = game:GetService("Players")
local Workspace = game:GetService("Workspace")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local SoundService = game:GetService("SoundService")
local mouse = Players.LocalPlayer:GetMouse()

local gridSize = 4
local partSize = Vector3.new(gridSize, gridSize, gridSize)
local previewUnion
local folder = Workspace:FindFirstChild("CurrentBlocks")
local toolEquipped = false
local remoteEvent = ReplicatedStorage:FindFirstChild("BlockPlacerRemote")
local soundId = 8265653733  -- ID of the sound to play

if not folder then
	folder = Instance.new("Folder")
	folder.Name = "CurrentBlocks"
	folder.Parent = Workspace
end

-- Function to snap positions to the grid
local function snapToGrid(position)
	return Vector3.new(
		math.round(position.X / gridSize) * gridSize,
		math.round(position.Y / gridSize) * gridSize,
		math.round(position.Z / gridSize) * gridSize
	)
end

-- Function to create and position the preview union
local function createPreviewUnion()
	if previewUnion then
		previewUnion:Destroy()
	end

	-- Clone the union from ReplicatedStorage
	local previewTemplate = ReplicatedStorage:FindFirstChild("Preview")
	if not previewTemplate then
		warn("Preview union not found in ReplicatedStorage")
		return
	end

	previewUnion = previewTemplate:Clone()
	previewUnion.Size = partSize
	previewUnion.CanCollide = false
	previewUnion.Anchored = true
	previewUnion.Parent = Workspace

	-- Position the previewUnion so its center aligns with the grid
	previewUnion.Position = snapToGrid(mouse.Hit.Position) + Vector3.new(0, partSize.Y / 2, 0) -- Centered above ground
end

-- Function to update the position of the preview union
local function updateUnionPosition()
	local targetPosition = snapToGrid(mouse.Hit.Position) + Vector3.new(0, partSize.Y / 2, 0) -- Center of the previewUnion
	local tweenInfo = TweenInfo.new(0, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut) -- 0 seconds duration
	local goal = { Position = targetPosition }
	local tween = TweenService:Create(previewUnion, tweenInfo, goal)
	tween:Play()

	-- Check if a block can be placed
	local canPlace = true
	for _, part in ipairs(Workspace:FindFirstChild("CurrentBlocks"):GetChildren()) do
		if part:IsA("Part") then
			if (part.Position - previewUnion.Position).magnitude < (partSize.X / 2 + partSize.X / 2) then
				canPlace = false
				break
			end
		end
	end

	-- Change color based on whether placement is possible
	if canPlace then
		previewUnion.BrickColor = BrickColor.new("Bright green")
	else
		previewUnion.BrickColor = BrickColor.new("Bright red")
	end
end

-- Function to play the sound effect
local function playSound()
	local sound = Instance.new("Sound")
	sound.SoundId = "rbxassetid://" .. soundId
	sound.Parent = SoundService
	sound:Play()
	-- Clean up the sound after it finishes playing
	sound.Ended:Connect(function()
		sound:Destroy()
	end)
end

Tool.Equipped:Connect(function()
	toolEquipped = true
	createPreviewUnion()
	while Tool.Parent do
		updateUnionPosition()
		wait(0.1)  -- Adjust the wait time to control the update frequency
	end
end)

Tool.Unequipped:Connect(function()
	toolEquipped = false
	if previewUnion then
		previewUnion:Destroy()
	end
end)

mouse.Button1Down:Connect(function()
	if toolEquipped and previewUnion and remoteEvent then
		-- Determine if placement is valid
		local canPlace = previewUnion.BrickColor == BrickColor.new("Bright green")
		local previewOrigin = previewUnion.Position - previewUnion.Size / 2 -- Origin of the previewUnion
		local position = previewOrigin + Vector3.new(partSize.X / 2, partSize.Y / 2, partSize.Z / 2) -- Center the block

		-- Apply a random easing style for tweening
		local easingStyles = Enum.EasingStyle:GetEnumItems()
		local randomEasingStyle = easingStyles[math.random(1, #easingStyles)]
		local tweenInfo = TweenInfo.new(0, randomEasingStyle, Enum.EasingDirection.InOut)
		local goal = { Position = position }
		local tween = TweenService:Create(previewUnion, tweenInfo, goal)
		tween:Play()

		-- Send a request to the server to place the block
		remoteEvent:FireServer(position, canPlace)

		-- Play the sound effect
		playSound()
	end
end)

figured it out after realizing someone on this forum also had this problem!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.