I am trying to create a placement system, and to get parts to be placeable correctly on walls and roofs, I am trying to edit the CFrame of the part being placed using the normal of the raycast, however, it is currently placing the block in the wrong position.
Relevant code:
local mouseRay = mouse.UnitRay;
local castRay = Ray.new(mouseRay.Origin, mouseRay.Direction * 1000);
local ignoreList = {clientStructure, char};
local tau = math.pi*2;
local hit, position, normal = workspace:FindPartOnRayWithIgnoreList(castRay, ignoreList);
local newCFrame = CFrame.new(position.X, position.Y + yBuildingOffset, position.Z) * CFrame.fromEulerAnglesXYZ(normal.X*tau, normal.Y*tau, normal.Z*tau);
clientStructure.CFrame = newCFrame;
Entire script (although most of this is unrelated to the problem):
local ReplicatedStorage = game:GetService("ReplicatedStorage");
local PlaceStructure = ReplicatedStorage:WaitForChild("PlaceEvent");
local Structures = ReplicatedStorage:WaitForChild("Structures");
local UIS = game:GetService("UserInputService");
local RunService = game:GetService("RunService");
local Player = game.Players.LocalPlayer;
local StructureFrame = script.Parent.StructureFrame;
local char = Player.Character or Player.Character:Wait();
local HumanoidRootPart = char:WaitForChild("HumanoidRootPart");
local mouse = Player:GetMouse();
local yBuildingOffset = 2;
local MaxPlacingDistance = 50;
local rKeyIsPressed = false;
local placingStructure = false;
local tau = math.pi*2;
local pi = math.pi;
for _, structureButton in pairs(StructureFrame:GetChildren()) do
if structureButton:IsA("TextButton") then
structureButton.MouseButton1Up:Connect(function()
StructureFrame.Visible = false;
local yorientation = 0;
local GoodToPlace = false;
local PlacedStructure;
if placingStructure == false then
placingStructure = true;
local clientStructure = Structures:FindFirstChild(structureButton.Name):Clone();
clientStructure.BrickColor = BrickColor.new("Forest green");
clientStructure.Transparency = 0.5;
clientStructure.Material = "Neon";
clientStructure.CanCollide = false;
clientStructure.Parent = game.Workspace;
local startingCFrame = CFrame.new(0, -2, -15);
clientStructure.CFrame = HumanoidRootPart.CFrame:ToWorldSpace(startingCFrame);
RunService.RenderStepped:Connect(function()
local mouseRay = mouse.UnitRay;
local castRay = Ray.new(mouseRay.Origin, mouseRay.Direction * 1000);
local ignoreList = {clientStructure, char};
local hit, position, normal = workspace:FindPartOnRayWithIgnoreList(castRay, ignoreList);
print(workspace:FindPartOnRayWithIgnoreList(castRay, ignoreList));
print(hit, position, normal);
if hit then
if (HumanoidRootPart.Position - clientStructure.Position).Magnitude < MaxPlacingDistance then
GoodToPlace = true;
clientStructure.BrickColor = BrickColor.new("Forest green");
else
GoodToPlace = false;
clientStructure.BrickColor = BrickColor.new("Crimson");
end;
end;
local newAnglesCFrame = CFrame.Angles(0, math.rad(yorientation), 0);
local newCFrame = CFrame.new(position.X, position.Y + yBuildingOffset, position.Z) * CFrame.fromEulerAnglesXYZ(normal.X*tau, normal.Y*tau, normal.Z*tau);
clientStructure.CFrame = newCFrame;
end)
UIS.InputBegan:Connect(function(input)
if input.KeyCode == Enum.KeyCode.R then
rKeyIsPressed = true;
local rotationSpeed = 5;
while rKeyIsPressed do
task.wait();
if placingStructure == true then
yorientation = yorientation + rotationSpeed;
end;
end;
end;
end);
UIS.InputEnded:Connect(function(Input)
if Input.KeyCode == Enum.KeyCode.R then
rKeyIsPressed = false;
end;
end);
UIS.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1 then
if placingStructure == true then
if GoodToPlace == true then
local StructureCFrame = clientStructure.CFrame;
PlaceStructure = PlaceStructure:FireServer(clientStructure.Name, StructureFrame);
if PlaceStructure == true then
PlaceStructure = false;
clientStructure:Destroy();
StructureFrame.Visible = true;
end;
end;
end;
end;
end);
end;
end);
end;
end;
Footage of error:
https://gyazo.com/1148ca47f98ff27c9b8e3ce1e8fffb32