Rotating parts in placement system

I am really struggling with rotating parts in a placement system. I have just started making a placement system.
When I rotate the part when clicking R it continues spinning forever.

-- Here is the script
UserInputService.InputChanged:Connect(function()
	if UserInputService:IsKeyDown(Enum.KeyCode.R) then
		print("Type")
			Model:SetPrimaryPartCFrame(Model.PrimaryPart.CFrame * CFrame.Angles(math.rad(Model.PrimaryPart.Orientation.X),math.rad(Model.PrimaryPart.Orientation.Y+90),math.rad(Model.PrimaryPart.Orientation.Z)))end

end)

UserInputService.InputChanged is fired when any input changes. Your function is not checking what kind of input events are being fired, which happens when all sorts of things change (mouse move, other keys pressed, etc.)

What you should do instead is try connecting to the event UserInputService.InputBegan, then check the InputObject given as the first argument for the key pressed. For example:

UserInputService.InputBegan:Connect(function(input, gameProcessedEvent)
    if input.KeyCode == Enum.KeyCode.R then
        Model:SetPrimaryPartCFrame(Model.PrimaryPart.CFrame * CFrame.Angles(math.rad(Model.PrimaryPart.Orientation.X),math.rad(Model.PrimaryPart.Orientation.Y+90),math.rad(Model.PrimaryPart.Orientation.Z)))
    end
end)

Alternatively, check out ContextActionService and BindAction, which would also make it easier to adapt it for touch and controller.

Edited Reply 2 :
It still does it.

Whole Code

local Model = game.ReplicatedStorage.Example:Clone()
local OriginalModelName = Model.Name
Model.Name = "Placing ".. OriginalModelName
Model.Parent = game.Workspace.CurrentCamera
local Mouse = game.Players.LocalPlayer:GetMouse()
local Touched = false

local UserInputService = game:GetService("UserInputService")

for _,v in pairs(Model:GetChildren()) do
	if v ~= Model.PrimaryPart then
		print("i")
		CCV = Instance.new("Color3Value")
		CCV.Parent = v
		CCV.Value = v.Color
		CCV.Name = "StartColor"
		SCV = Instance.new("BoolValue")
		SCV.Parent = v
		SCV.Name = "StartCollision"
		SCV.Value = v.CanCollide
		v.CanCollide = false
	end
end

Mouse.Button1Down:Connect(function()
	if Touched == false then
		game.ReplicatedStorage.PlaceObject:FireServer(Model.PrimaryPart.Position.X,Model.PrimaryPart.Position.Y,Model.PrimaryPart.Position.Z,OriginalModelName,SCV,Model.PrimaryPart.Orientation.X,Model.PrimaryPart.Orientation.Y,Model.PrimaryPart.Orientation.Z)
		for _,v in pairs(Model:GetChildren()) do
			if  v ~= Model.PrimaryPart then
				v.BrickColor = BrickColor.new("Really red")
			end
		end
	end
end)
UserInputService.InputBegan:Connect(function(input, gameProcessedEvent)
    if input.KeyCode == Enum.KeyCode.R then
        Model:SetPrimaryPartCFrame(Model.PrimaryPart.CFrame * CFrame.Angles(math.rad(Model.PrimaryPart.Orientation.X),math.rad(Model.PrimaryPart.Orientation.Y+90),math.rad(Model.PrimaryPart.Orientation.Z)))
    end
end)







while wait() do
	Touched = false
	if Mouse.Target ~= nil then
		Mouse.TargetFilter = Model
		if not UserInputService:IsKeyDown(Enum.KeyCode.LeftShift) or UserInputService:IsKeyDown(Enum.KeyCode.RightShift) then
			Model:SetPrimaryPartCFrame(
				CFrame.new(
						math.floor(Mouse.Hit.X),
						Mouse.Hit.Y +  (Model.PrimaryPart.Size.Y/2) , 
						math.floor(Mouse.Hit.Z)
					
					)
					*
					CFrame.fromOrientation(
						Model.PrimaryPart.Orientation.X,
						Model.PrimaryPart.Orientation.Y,
						Model.PrimaryPart.Orientation.Z
				)
			)
		else
			Model:SetPrimaryPartCFrame(
				CFrame.new(
						Mouse.Hit.X,
						Mouse.Hit.Y +  (Model.PrimaryPart.Size.Y/2) , 
						Mouse.Hit.Z
					
					)
					*
					CFrame.fromOrientation(
						Model.PrimaryPart.Orientation.X,
						Model.PrimaryPart.Orientation.Y,
						Model.PrimaryPart.Orientation.Z
				)
			)
		end
		local Touch = Model.PrimaryPart:GetTouchingParts()
		for _,v in pairs(Touch) do
			if v.Parent ~= Model and v.Locked == false and not v:IsA("WedgePart") then
				Touched = true
			end
			
		end
		
	end
	
	if Touched == true then
		for _,v in pairs(Model:GetChildren()) do
			if  v ~= Model.PrimaryPart then
				v.BrickColor = BrickColor.new("Really red")
			end
		end
	else
		for _,v in pairs(Model:GetChildren()) do
			if v ~= Model.PrimaryPart then
				if CCV then
					v.Color = v:FindFirstChild(CCV.Name).Value
					
				end -- if CCV
			end -- if v ~=
		end -- for
	end -- if Touched == true then
end -- While wait() do

lua

Here’s a short example using BindAction:

local ContextActionService = game:GetService('ContextActionService')

local function RotateAction(ActionName, InputState, InputObject)
	if InputState == Enum.UserInputState.Begin then
		Model:SetPrimaryPartCFrame(Model.PrimaryPart.CFrame * CFrame.Angles(math.rad(Model.PrimaryPart.Orientation.X),math.rad(Model.PrimaryPart.Orientation.Y+90),math.rad(Model.PrimaryPart.Orientation.Z)))
	end
end

ContextActionService:BindAction('RotatePart', RotateAction, true, Enum.KeyCode.R, Enum.KeyCode.ButtonX)
  • ‘RotatePart’ is the action name
  • RotateAction is the function to call
  • true is to create a touch button for mobile
  • The rest are keys and buttons to listen for

There’s also UnbindAction when you want to stop the action from firing.

This still continues to happen with BindAction and InputBegan

Maybe there’s something going on the setting the CFrame in the while loop? (The lines after Mouse.TargetFilter = Model) That’s the only other thing I can see that modifies the model CFrame. I can’t seem to find anything wrong though. Do you have any other scripts that modify the model?

No I only have the server script which sends it out to the server. The only reason why I made the cframe in a loop is so it won’t glitch. It did that in my really old messy script.

You might need some parentheses for this if expression, to be entirely sure it does what you want it to do:

if not UserInputService:IsKeyDown(Enum.KeyCode.LeftShift) or UserInputService:IsKeyDown(Enum.KeyCode.RightShift) then

Because as how it is written (without parentheses), its truth table looks like this:

NOT 'LeftShift' OR 'RightShift' -> Result
-----------------------------------------
NOT  false      OR  false       -> true
NOT  false      OR  true        -> true
NOT  true       OR  false       -> false
NOT  true       OR  true        -> true

But if you add parentheses like this:

if not ( UserInputService:IsKeyDown(Enum.KeyCode.LeftShift) or UserInputService:IsKeyDown(Enum.KeyCode.RightShift) ) then

It becomes:

NOT ( 'LeftShift' OR 'RightShift' ) -> Result
-----------------------------------------
NOT ( false      OR  false        ) -> true
NOT ( false      OR  true         ) -> false
NOT ( true       OR  false        ) -> false
NOT ( true       OR  true         ) -> false

Here is a simple Lua script that proves it:

print("")
print("-- not leftShift or rightShift --")
for _,leftShift in ipairs({ false, true }) do
	for _,rightShift in ipairs({ false, true }) do
		local result = not leftShift or rightShift
		print("NOT",leftShift,"OR",rightShift,"->",result)
	end
end

print("")
print("-- not ( leftShift or rightShift ) --")
for _,leftShift in ipairs({ false, true }) do
	for _,rightShift in ipairs({ false, true }) do
		local result = not ( leftShift or rightShift )
		print("NOT (",leftShift,"OR",rightShift,") ->",result)
	end
end

I got rid of that code and replaced it with the one you sent me. It still continues to happen. What I might do is try to retype parts of the script. Thanks for helping!

I found out that it is the beginning of the script. I will edit this myself. Thank you!