Does Anyone know how to position placeables onto the floor perfectly

Hello, I am attempting to do a placeables script and so far its gone amazingly. However the placeables can be cast on a table leg or on a wall. I don’t want that i want it so that it can’t be placed onto a wall or table leg and the colour will change red if it can’t be placed there, It can also be placed onto another candle which i don’t want. Does anyone have any idea how to fix this issue?

Local Script:

local Player = game.Players.LocalPlayer
local Character = Player.Character

local RunService = game:GetService("RunService")
local CandleTemplate = script.Parent.Handle

local preview = nil
local UIS = game:GetService("UserInputService")

local castParams = RaycastParams.new()
castParams:AddToFilter(Character)

local function PreparePreviewPart(part)
	preview = part:Clone()
	preview.Parent = workspace
	preview.CanCollide = false
	preview.CanQuery = false
	preview.Anchored = true
	preview.Color = Color3.new(1,1,1)
	preview.Transparency = 0.5
	preview.Orientation = Vector3.new(0, -90, 0)
end

local function renderPreview()
	local mouseloc = UIS:GetMouseLocation()
	local unitray = workspace.CurrentCamera:ViewportPointToRay(mouseloc.X, mouseloc.Y)
	local cast = workspace:Raycast(unitray.Origin, unitray.Direction * 1000, castParams)
	if cast and preview then
		preview.Position = cast.Position + cast.Normal * CandleTemplate.Size.Y/2
		
	end
end

task.spawn(function()
	UIS.InputBegan:Connect(function(MS)
		if MS.UserInputType == Enum.UserInputType.MouseButton1 then
			game.ReplicatedStorage.Placeable:FireServer(CandleTemplate, preview.Position, preview.Orientation, script.Parent.Name)
			preview:Destroy()
			script.Parent:Destroy()
		end
	end)
end)

script.Parent.Unequipped:Connect(function()
	preview:Destroy()
end)

PreparePreviewPart(CandleTemplate)

RunService:BindToRenderStep("Preview", Enum.RenderPriority.Camera.Value, renderPreview)

Server Script:

game.ReplicatedStorage.Placeable.OnServerEvent:Connect(function(Player, Item, Position, Orientation, Name)
	local Clone = Item:Clone()
	Clone.Parent = workspace
	Clone.Position = Position
	Clone.Orientation = Orientation
	Clone.Anchored = true
	Clone.Name = Name
end)

Video may show a bit more:

First method:
Shoot ray downwards from mouse location so its always on ground

local function renderPreview()
	local mouseloc = UIS:GetMouseLocation()
	local unitray = workspace.CurrentCamera:ViewportPointToRay(mouseloc.X, mouseloc.Y)
	
	local mousePos = workspace:Raycast(unitray.Origin, unitray.Direction * 1000, castParams)
	
	local origin = CFrame.new(mousePos.Position) * CFrame.new(0,8,0);
	local endPoint = CFrame.new(mousePos.Position) * CFrame.new(0,-64,0);
	
	local direction = endPoint - origin;
	
	local cast = workspace:Raycast(origin, direction, castParams)
	
	if cast and preview then
		preview.Position = cast.Position + cast.Normal * CandleTemplate.Size.Y/2
	end
end

Second method:
Shoot ray downwards from mouse location and change its color to red if the distance is greater than 0.1 studs

local function renderPreview()
	local mouseloc = UIS:GetMouseLocation()
	local unitray = workspace.CurrentCamera:ViewportPointToRay(mouseloc.X, mouseloc.Y)
	local cast = workspace:Raycast(unitray.Origin, unitray.Direction * 1000, castParams)
	
	local checkGround = workspace:Raycast(cast.Position * Vector3.new(0,0.05,0), (Vector3.new(0,-64,0)*cast) - cast, castParams);
	
	if cast and preview then
		if cast - checkGround.Position < 0.1 then
			preview.Position = cast.Position + cast.Normal * CandleTemplate.Size.Y/2
		else
			preview.Color = Color3.fromRGB(255, 0, 0);
		end
	end
end

These aren’t tested so if there are any errors please let me know.

none of these sadly worked, I cnp both of them however they are still the same as before

Try this
Fixed first method

local function renderPreview()
	local mouseloc = UIS:GetMouseLocation()
	local unitray = workspace.CurrentCamera:ViewportPointToRay(mouseloc.X, mouseloc.Y)

	local mousePos = workspace:Raycast(unitray.Origin, unitray.Direction * 1000, castParams)
	if mousePos then
		local origin = CFrame.new(mousePos.Position) * CFrame.new(0,8,0);
		local endPoint = CFrame.new(mousePos.Position) * CFrame.new(0,-64,0);

		local direction = endPoint.Position - origin.Position;

		local cast = workspace:Raycast(origin.Position, direction, castParams)

		if cast and preview then
			preview.Position = cast.Position + cast.Normal * CandleTemplate.Size.Y/2
		end
	end
end

Fixed second method

local function renderPreview()
	local mouseloc = UIS:GetMouseLocation()
	local unitray = workspace.CurrentCamera:ViewportPointToRay(mouseloc.X, mouseloc.Y)
	local mousePos = workspace:Raycast(unitray.Origin, unitray.Direction * 1000)
	
	if mousePos then
		local origin = CFrame.new(mousePos.Position) * CFrame.new(0,0.05,0);
		local endPoint = CFrame.new(mousePos.Position) * CFrame.new(0,-32,0);
		local direction = endPoint.Position - origin.Position;
		
		local checkGround = workspace:Raycast(origin.Position, direction);
		local distance:number = mousePos.Position.Y - checkGround.Position.Y;

		if distance < 0.1 then
			previewPart.Position = mousePos.Position + mousePos.Normal;
			previewPart.Color = Color3.fromRGB(255, 255, 255);
		else
			previewPart.Color = Color3.fromRGB(255, 0, 0);
		end
	end
end

If possible create a boolean variable when the object is red so the user cant place it

sadly still has the same outcome, can place on walls and ontop of other candles.

Try the fixed second method if it works

Also if you don’t want it to place it ontop of other candles then set the objects CanQuery to false

part.CanQuery = false;

also it worked fine for me:

I’ve tried both of them sadly do not work i can still place onto walls and stuff

I think this maybe more difficult because I’m assuming the wall you have are not flat like mine so that means you would need to add the list of parts/objects to the exclude in the raycast parameters. Try to get all the parts that you dont want it to place it on and add it to the raycast parameters.

ahh nvm it works tysm its cause i have 4 different tools with individual scripts

Haha it’s alright, happens to me too sometimes. Anyways good luck on your game! Hope I can play it someday :smiley: :heart:

thank you so much, I’ve decided to go with the method 1

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