Issue with building system

I have created a building system and I followed this tutorial, everything is working smoothly except for this small issue.

  1. What do you want to achieve? The wall gets placed at the mouse’s position.

  2. What is the issue? The wall gets placed but the Y-axis keeps being changed and going into the ground with different values every time.

Examples

Example 1:

Gif

Example 2:

^ All put by the same system, different Y-axis every time even though I placed them on the same terrain.

  1. What solutions have you tried so far? I have tried to change the script a little bit and optimize it but it doesn’t seem like I can solve it myself.

Here are the scripts that I used for this.

The LocalScript located in the ScreenGUI:

local Rep = game:GetService('ReplicatedStorage');
local PlaceStructure = Rep:WaitForChild('PlaceStructure');
local MainFrame = script.Parent.MainFrame;
local Structures = Rep:WaitForChild('Structures');
local UIS = game:GetService('UserInputService');
local RunService = game:GetService('RunService');

local Player = game.Players.LocalPlayer;
local StructureFrame = script.Parent.MainFrame.StructureFrame;
local char = Player.Character or Player.Character:Wait();
local HumanoidRootPart = char:WaitForChild('HumanoidRootPart');
local MouseClicked = false;

local Mouse = Player:GetMouse();

local yBuildingOffset = 5;
local MaxPlacingDistance = 50;
local rKetIsPressed = false;
local PlacingStructure = false;

for _, StructureButton in pairs(StructureFrame.Structures:GetChildren()) do
	if StructureButton:IsA('TextButton') then
		StructureButton.MouseButton1Up:Connect(function()

			MainFrame.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('Bright green');
				ClientStructure.Material = 'Neon';
				ClientStructure.CanCollide = false;
				ClientStructure.Parent = 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 = workspace:FindPartOnRayWithIgnoreList(CastRay, ignoreList);

					if hit and (HumanoidRootPart.Position - ClientStructure.Position).Magnitude < MaxPlacingDistance then
						goodToPlace = true;
						ClientStructure.BrickColor = BrickColor.new('Bright green');
					else
						goodToPlace = false;
						ClientStructure.BrickColor = BrickColor.new('Crimson');
					end

					local newAnglesCFrame = CFrame.Angles(0, math.rad(yOrientation), 0);
					local newCFrame = CFrame.new(position.X, position.Y + yBuildingOffset, position.Z);
					ClientStructure.CFrame = newCFrame * newAnglesCFrame;
				end)

				UIS.InputBegan:Connect(function(Input)
					if Input.KeyCode == Enum.KeyCode.R then
						rKetIsPressed = true;

						local rotationSpeed = 5;

						while rKetIsPressed do
							wait();

							if PlacingStructure == true then
								yOrientation = yOrientation + rotationSpeed;
							end
						end
					end
				end)

				UIS.InputEnded:Connect(function(input)
					if input.KeyCode == Enum.KeyCode.R then
						rKetIsPressed = false;
					end
				end)

				UIS.InputBegan:Connect(function(input)
					if input.UserInputType == Enum.UserInputType.MouseButton1 and MouseClicked == false then
						MouseClicked = true;
						if PlacingStructure == true then
							if goodToPlace == true then
								local StructureCFrame = ClientStructure.CFrame;
								PlacedStructure = PlaceStructure:InvokeServer(ClientStructure.Name, StructureCFrame);

								if PlacedStructure == true then
									PlacingStructure = false;
									ClientStructure:Destroy();
									MainFrame.Visible = true;
								end
							end
						end
						MouseClicked = false;
					end
				end)
			end
		end)
	end
end

The ServerScript in ServerScriptService:

local Rep = game:GetService('ReplicatedStorage');
local PlaceStructure = Rep:WaitForChild('PlaceStructure');
local Structures = Rep:WaitForChild('Structures');

PlaceStructure.OnServerInvoke = function(Player, StructureName, StructureCFrame)
	
	local Crafted;
	local RealStructure = Structures:FindFirstChild(StructureName):Clone();
	
	if RealStructure then
		RealStructure.Anchored = true;
		RealStructure.CFrame = StructureCFrame;
		RealStructure.Parent = game.Workspace;
		Crafted = true;
	else
		Crafted = false;
	end
	
	return Crafted;

I just couldn’t find the solution at all, the Y-axis keeps being changed every time I place a new wall and it goes under the ground. It would be appreciated if you could help me solve this issue. (:

I believe you have to add half of the size of the part you are building. This is because the position of the part is always in the center, not the side/bottom of the part. Hope this helps!

How so? And in which part? Do you mean to add half the size of the part to the Y-axis or…?

Yes, I did that on purpose. One for the mouse click and the other is for the rotation.

The Y offset will always be half the Size.Y. So just get the vertical size of the part you are placing and divide that by two. That would offset the part so the base touches the ground.

Okay, so I found out that the Y-axis of the clientStructure keeps going down the longer you hold it, example:

Example

Any idea why this is happening?

The reason is due to mouse.Hit.Position, it goes all the way down. What you need is offsetting. Use this to offset the part part1.Size.Y / 2 + part2.Size.Y / 2 + part1.Position.Y.

Demonstration:

part.Position + Vector3.new(0, plot.Size.Y / 2 + part.Size.Y / 2 + plot.Position.Y, 0)