I am creating a placement system in which you can only place on certain parts.
Here’s my testing code:
local LocalPlayer = game:GetService("Players").LocalPlayer
local Mouse = LocalPlayer:GetMouse()
local RaycastParam = RaycastParams.new()
RaycastParam.IgnoreWater = true
RaycastParam.FilterType = Enum.RaycastFilterType.Whitelist
RaycastParam .FilterDescendantsInstances = {workspace.PlacementParts}
local Tool = script.Parent
local Equipped = false
Tool.Equipped:Connect(function()
Equipped = true
end)
Tool.Unequipped:Connect(function()
Equipped = false
end)
game:GetService("RunService").RenderStepped:Connect(function()
if Equipped then
local Hit = Mouse.Hit
local Raycast = Ray.new(
Hit.p,
Vector3.new(0,-1,0)*500
)
local RaycastResult = workspace:Raycast(Hit.p, Vector3.new(0,-1,0)*500, RaycastParam)
if RaycastResult and RaycastResult.Position then
local Part = Instance.new("Part")
Part.Parent = workspace
Part.Position = RaycastResult.Position
Part.Anchored = true
task.delay(.1, function()
Part:Destroy()
end)
end
end
end)
workspace.PlacementParts is the folder in which the parts you can place on are stored.
When testing however, you can only place on parts above the parts in the folder:
Hovering over the part itself isn’t working:
I see 3 parts. Something Green, something Red, and something clear and white. Can you add a print(RaycastResult.Instance) to make sure your not running into the filter? Also, this line has an unwanted space:
local RaycastResult = workspace:Raycast(Hit.p + Vector3.new(0,0.001,0), Vector3.new(0,-500,0), RaycastParam)
I think the raycast is erroring because the ray is being casted in the part, not on top it. Adding 0.001 makes it slightly above the part making the ray fully go through it.
I would need to see the workspace folder setup, but I think you filtered a folder that these parts are in. The ray is missing both the green and the white.
Also check your “cantouch” and “canquery” properties.
LOL, I was running in circles! OK, green is not filtered but white is… and neither are filtered for the Mouse.Hit, but the white part has collide turned off. (throws out the rulebook)
OK, a few more suggestions.
can you test print(Mouse.Target) to make sure the white part is actually the start of the raycast? It should be.
is the white part overlapping the green part? If so, raise the white part up and make it thinner. @deafaultyboii1324 might be right about the problem, but wrong about the correction necessary.
Maybe create a part at Hit.p? When all else fails, throw a part out there. No need to write anything new, try this:
local function addball (pos, size)
local ball = Instance.new("Part")
ball.BrickColor = BrickColor.new("Really red")
ball.Shape = "Ball"
ball.Size = Vector3.new(size,size,size)
ball.Anchored = true
ball.Position = pos
ball.Parent = game.Workspace
end
The only thing your raycast should find is the white part. The reason it works on the red part is simple: Mouse hits the red, you raycast through it and hit the white.
I thought whitelist meant that only the supplied parts can be found by a raycast? I made the edit and now any part, including those outside of the placement area, can be selected. I am thinking an easier solution might be to have raycasting on for everywhere and check if the part is within a placement region using region3.
It does. The only part you can find in the whitelist is the white part. However, you already found the white part with the mouse hit, and you are raycasting from there. You can’t find the white part again, as you are already inside it.
2 scenarios:
Mouse.hit on the white part. Raycast down from the white part finds nothing (only thing under white is green, not whitelisted).
Mouse.hit on the red part. Raycast down from the red part finds the white part.
It looks like you want the white part to be the “region” You can do that by blacklisting the white part, but you also need to add the check that the Mouse.Target is the white part.
local LocalPlayer = game:GetService("Players").LocalPlayer
local Mouse = LocalPlayer:GetMouse()
local RaycastParam = RaycastParams.new()
RaycastParam.IgnoreWater = true
RaycastParam.FilterType = Enum.RaycastFilterType.Whitelist
RaycastParam.FilterDescendantsInstances = {workspace.Map}
local Tool = script.Parent
local Equipped = false
Tool.Equipped:Connect(function()
Equipped = true
end)
Tool.Unequipped:Connect(function()
Equipped = false
end)
function isInsideBrick(position, brick)
local v3 = brick.CFrame:PointToObjectSpace(position)
return (math.abs(v3.X) <= brick.Size.X / 2)
and (math.abs(v3.Y) <= brick.Size.Y / 2)
and (math.abs(v3.Z) <= brick.Size.Z / 2)
end
function CheckPosition(Position)
for _, Part in pairs(workspace.PlacementParts:GetChildren()) do
if isInsideBrick(Position, Part) then
return true
end
end
return false
end
game:GetService("RunService").RenderStepped:Connect(function()
if Equipped then
local Hit = Mouse.Hit
local Raycast = Ray.new(
Hit.p+Vector3.new(0,10,0),
Vector3.new(0,-1,0)*500
)
local RaycastResult = workspace:Raycast(Hit.p, Vector3.new(0,-1,0)*500, RaycastParam)
if RaycastResult and RaycastResult.Position and CheckPosition(RaycastResult.Position) then
local P = Instance.new("Part", workspace)
P.Position = RaycastResult.Position
P.Anchored = true
delay(.1, function()P:Destroy()end)
end
end
end)