Placement System Problem and Surface and Terrain

I just made my placement system but heres the thing, How do I make my part’s Height position to be dependent on what surface level or terrain level It Is currently on? Like making my part on top of the surface it is on when my cursor is on a higher surface level? Also my placement system snaps to world grid thats what i made but when I make the part very far from my character It snaps to world grid twice like it was meant to be at the exact mouse position but its position was then lerped to another position that is still at the exact cursor position.

This Is my placement system

local userinputservice = game:GetService("UserInputService")
local runservice = game:GetService("RunService")

local block = game.Workspace:WaitForChild("Block")

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

runservice.RenderStepped:Connect(function()
	local mouseposition = mouse.Hit.Position
	
	local x = math.round(mouseposition.X)
	local z = math.round(mouseposition.Z)
	
	block.Position = Vector3.new(x, block.Position.Y, z)
end)



As you can see In the video thats the exact problem Im talking about when i moved my cursor far In the baseplate and In the spawnpoint.

I need an answer and an solution and please tell what I need to Improve.

1 Like

Hey there! You can use this code:

local runservice = game:GetService("RunService")

local block = game.Workspace:WaitForChild("Block")

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

local maxDistance = 999 -- max distance player can place block
local gridSnapSize = 1 -- the size of the grid that the block snaps to

local function gridSnap(value: number | Vector3, gridSize: number)
	if typeof(value) == "Vector3" then
		return Vector3.new(
			math.floor(value.X / gridSize + 0.5) * gridSize,
			math.floor(value.Y / gridSize + 0.5) * gridSize,
			math.floor(value.Z / gridSize + 0.5) * gridSize
		)
	elseif typeof(value) == "number" then
		return math.floor(value / gridSize + 0.5) * gridSize
	end
end

runservice.RenderStepped:Connect(function()	
	local raycastParams = RaycastParams.new()
	raycastParams.FilterType = Enum.RaycastFilterType.Exclude
	raycastParams.FilterDescendantsInstances = {player.Character,  block}
	local raycastResult = workspace:Raycast(mouse.UnitRay.Origin, mouse.UnitRay.Direction * maxDistance, raycastParams)
	
	if raycastResult then
		local targetPosition = raycastResult.Position + (Vector3.yAxis * block.Size.Y/2)
		block.Position = gridSnap(targetPosition, gridSnapSize)
	end
end)
2 Likes

Here is a super simple solution using a raycast, I recommend putting the part into a model and using :PivotTo() but that is not required.

local runservice = game:GetService("RunService")

local block = game.Workspace:WaitForChild("Block")

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

local maxdistance = 100 -- The distance in studs until the preview will stop updating

runservice.RenderStepped:Connect(function()
	local RaycastP = RaycastParams.new()
	RaycastP.FilterType = Enum.RaycastFilterType.Exclude
	RaycastP.FilterDescendantsInstances = {player.Character, block}
	
	local mouseposition = workspace:Raycast(mouse.Origin.Position, mouse.Origin.LookVector * maxdistance, RaycastP)
	
	if mouseposition then
		local x = math.round(mouseposition.Position.X)
		local z = math.round(mouseposition.Position.Z)
		local y = math.round(mouseposition.Position.Y) + block.Size.Y / 2
		block.Position = Vector3.new(x, y, z)
	end
end)

this can be the solution but since im still a decent scripter I still need it to be more simple, no need to respond again thank you for helping

@twc89403 literally just copied and pasted my code but made it worse. My code allows you to change the grid size that you want the block to snap to. I have no idea why you marked this stolen code as the solution.

Copied

Copied

Copied

Copied but “simplified” so it’s worse

Copied the + block.Size.Y / 2


Feel ashamed of yourself ngl; that’s pretty petty. Oh, and guess what? His profile is hidden. What a coincidence!

2 Likes

I did not intend or try to steal your code it is simply a basic raycast, the block.Size.Y is just simple math because the part isnt a model the only way to get the height from the pivot point of the part is by dividing Y / 2.

My profile being private is something im not sure about as it is set to public.

1 Like

Thank you for the clarification. It seems that there was a misunderstanding. There were no replies for over 2 hours, but just 30 minutes later, your reply (which was quite similar to mine) was posted here. Additionally, at the time, your DevForum profile was appearing as private. I’m not sure if that was recently changed or was due to a bug in the website. Lastly, your username consists of 3 random letters and a random 5-digit number. I hope you can see where my suspicion stemmed from.

I did look into it on some alts and noticed that for some reason only 1/8 the time I checked my profile it appeared as public, I think it is some sort of dev forum bug.

1 Like

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