Hello there!
I got into raycasting a few days ago and decided to try out making a placement system.
My goal is to achieve a simple placement system which supports placing down models or parts, moving them and rotating them.
The issue is when you rotate a part, it starts to clip though the surface of other parts (The surface normal becomes weird and the part doesn’t stick to the surface the mouse is pointing at.)
Normal behavior without rotation:
The issue after I rotate:
I’ve read many posts on the devforum and I’ve tried changing the values, but it just breaks the whole system.
(The models I use are just simple models with PrimaryParts.
LocalScript inside StarterPlayerScripts.
-- Services
local UIS = game:GetService("UserInputService")
-- Variables
local player = game:GetService("Players").LocalPlayer
local mouse = player:GetMouse()
local target
local position
local normal
local models = workspace.Models
local gridSize = 0.1
local rotation = 0
local item
wait(2)
-- Functions
for i, model in pairs(models:GetChildren()) do
local button = Instance.new("TextButton", player.PlayerGui.PlacementGui.ScrollingFrame)
button.Size = UDim2.new(1,-12,0,50)
button.ZIndex = 2
button.Text = model.Name
button.Name = model.Name
end
for i, button in pairs(player.PlayerGui.PlacementGui.ScrollingFrame:GetChildren()) do
if button and button:IsA("TextButton") then
button.MouseButton1Click:Connect(function()
print(button.Text)
if item ~= nil then item:Destroy() end
item = models[button.Text]:Clone()
item.Parent = workspace
end)
end
end
local function RayCast()
local ray = Ray.new(workspace.CurrentCamera.CFrame.p, (mouse.Hit.p - workspace.CurrentCamera.CFrame.p).unit * 64)
target, position, normal = workspace:FindPartOnRayWithIgnoreList(ray, {player.Character, item})
if position ~= nil and target ~= nil and normal ~= nil then
--print(position)
--print(target.Name)
--print(normal)
end
end
local function Position(part)
local x = math.floor((position.X + (normal.X * (part.Size.X / 2))) / gridSize + 0.5) * gridSize
local y = math.floor((position.Y + (normal.Y * (part.Size.Y / 2))) / gridSize + 0.5) * gridSize
local z = math.floor((position.Z + (normal.Z * (part.Size.Z / 2))) / gridSize + 0.5) * gridSize
return x, y, z
end
local function Move()
if item ~= nil and item.PrimaryPart then
local x, y, z = Position(item.PrimaryPart)
item:SetPrimaryPartCFrame(CFrame.new(x, y, z) * CFrame.Angles(0, math.rad(rotation), 0))
end
end
mouse.Button1Down:Connect(function()
if item ~= nil then
item:Clone().Parent = workspace
end
end)
UIS.InputBegan:Connect(function(inputObject, gPe)
if gPe then return end
if inputObject then
if inputObject.KeyCode == Enum.KeyCode.X then
print("X")
if item ~= nil then item:Destroy() end
elseif inputObject.KeyCode == Enum.KeyCode.R then
rotation = rotation + 90
if rotation == 360 then rotation = 0 end
print(rotation)
end
end
end)
game:GetService("RunService").RenderStepped:Connect(function()
RayCast()
Move()
end)
Thanks in advance, any help would be great