SetPrimaryPartCFrame not working as intended

I’m trying to make a road placement system. The road is a model.
Here is the code that matters:

RunService:BindToRenderStep("displayRoad", 1, function()
    if mouse.Target == workspace.Baseplate or mouse.Target == newRoad then
		local distance = (startingPoint - mouse.Hit.Position).magnitude
							
			for i, v in pairs(newRoad:GetChildren()) do
			    v.Size =  Vector3.new(v.Size.X, v.Size.Y, distance)
				v.Orientation = Vector3.new(0, v.Orientation.Y, 0)
			end
        
        newRoad:SetPrimaryPartCFrame(CFrame.new(startingPoint, mouse.Hit.Position) * CFrame.new(0,0, -distance / 2))
	end
end)

newRoad is the road model.

here is my entire code if you want to see it
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")

local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoidRootPart = character:WaitForChild("HumanoidRootPart")

local mouse = player:GetMouse()
local camera = workspace.CurrentCamera

local screenGui = script.Parent
local button = screenGui.TextButton
local label = screenGui.TextLabel

local road = ReplicatedStorage:WaitForChild("road", 5)

local choosingStart = false
local placingRoad = false

local remoteFunction = game.ReplicatedStorage:WaitForChild("RemoteFunction",3)

local maxPlaceDistance = 50


button.MouseButton1Click:Connect(function()
	print("the button was clicked", choosingStart)

	if choosingStart == false then
		print("the button was clicked")
		choosingStart = true
		button.Visible = false
		label.Visible = true
		label.Text = "click where you want to start"

		local newRoad = road:Clone()

		UserInputService.InputBegan:Connect(function(input)
			print("there is input")
			if placingRoad == false and input.UserInputType == Enum.UserInputType.MouseButton1 and placingRoad == false then
				print("player clicked")

				placingRoad = true

				local part = mouse.Target
				local startingPoint = mouse.Hit.Position				

				if part and part == workspace.Baseplate and (startingPoint - humanoidRootPart.Position).magnitude < maxPlaceDistance then
					newRoad.Parent = workspace

					RunService:BindToRenderStep("displayRoad", 1, function()
						if mouse.Target == workspace.Baseplate or mouse.Target == newRoad then
							local distance = (startingPoint - mouse.Hit.Position).magnitude
							
							for i, v in pairs(newRoad:GetChildren()) do
								v.Size =  Vector3.new(v.Size.X, v.Size.Y, distance)
								v.Orientation = Vector3.new(0, v.Orientation.Y, 0)
							end

							newRoad:SetPrimaryPartCFrame(CFrame.new(startingPoint, mouse.Hit.Position) * CFrame.new(0,0, -distance / 2))
						end
					end)
				end
			elseif placingRoad and input.UserInputType == Enum.UserInputType.MouseButton1 then

				local part = mouse.Target
				local startingPoint = mouse.Hit.Position	

				if part and part == workspace.Baseplate and (startingPoint - humanoidRootPart.Position).magnitude < maxPlaceDistance then
					placingRoad = false

					local placed = remoteFunction:InvokeServer(newRoad.Size, newRoad.CFrame)
				end
			end
		end)
	end
end)

The code is in a localScript

Here is the original road model:


this is how I want the road to appear, but if I play, every part gets centralized. Here is what I mean:
robloxapp-20201121-2048130.wmv (403.8 KB)
I want the road to look like the original. I’m probably doing something wrong with SetPrimaryPartCFrame()

First off, are there any errors in the console? Gives us a better clue on what’s going on.

I can’t spot a definition for newRoad except in the function within button.MouseButton1Click:Connect(), where it’s locally defined as local newRoad = road:Clone(). Perhaps making the variable global could be a fix?

there are no errors and

The clone of the road model I should say. It is in the replicatedStorage

Gotcha, didn’t notice that the function was within button.MouseButton1Click:Connect(function())

I have a suspicion that because you’re setting the size and orientation of each child of the road model before even plugging the location of the model, it’s messing up the local placement of each element within the model. Try putting

for i, v in pairs(newRoad:GetChildren()) do
	v.Size =  Vector3.new(v.Size.X, v.Size.Y, distance)
	v.Orientation = Vector3.new(0, v.Orientation.Y, 0)
end

after

newRoad:SetPrimaryPartCFrame(CFrame.new(startingPoint, mouse.Hit.Position) * CFrame.new(0,0, -distance / 2))

That didn’t work, it is still working the same.

Can someone help me? This is still not fixed

Can you provide the road model? It sounds like all of your parts are joined incorrectly or improper anchoring is causing them to move.

Schermopname (14)
here is the road, a picture is in the post

I meant the model itself. There’s not much we can infer from a picture.


here it is

I’d only be able to assume this is happening because you are changing the orientation of each part individually.

Instead of changing the orientation of each part, add a rotational CFrame to the SetPrimaryPartCFrame line.

you could do something like

    newRoad:SetPrimaryPartCFrame( CFrame.lookAt( startingPosition, newRoad.PrimaryPart.Position + Vector3.new(0, v.Orientation.Y, 0) ) )

Using the model provided, I ran this modified version of your code.

local camera = workspace.CurrentCamera
RunService:BindToRenderStep("displayRoad", 1, function()
	local mousePosition = game:GetService("UserInputService"):GetMouseLocation()
	local unitRay = camera:ScreenPointToRay(mousePosition.X, mousePosition.Y)
	local params = RaycastParams.new()
	params.FilterType = Enum.RaycastFilterType.Blacklist
	params.FilterDescendantsInstances = {newRoad, game.Players.LocalPlayer.Character}
	local result = workspace:Raycast(unitRay.Origin, unitRay.Direction * 500, params)
	if (result) then
		local targetPos = result.Position
		local distance = (startingPoint - targetPos).magnitude

		for i, v in pairs(newRoad:GetChildren()) do
			v.Size =  Vector3.new(v.Size.X, v.Size.Y, distance)
		end
		
		newRoad:SetPrimaryPartCFrame(CFrame.new(startingPoint, targetPos) * CFrame.new(0,0, -distance / 2))
	end
end)

And I got this result

Here’s a place file you can test out to see if there’s any differences. My script is in the StarterPlayerScripts

roadPoint.rbxl (22.4 KB)