Block spins in 270 orientation when tweening

So I’m making a very simple building system and I have a problem. I made the standard R to rotate system, however, when the block is 270 degrees it just starts spinning rapidly. It stops spinning when I rotate it back to 0 degrees.

Here is an example of the problem:

I tried looking this up and found someone with a similar problem, but with a solution that won’t work for me. If it helps, the system shows 2 blocks, a fake block that has all the tweening to make it look nice, and an invisible block that is where the blocks are being placed so the tweening doesn’t offset placement.

Local Script:

local cam = workspace.CurrentCamera
local gui = game.Players.LocalPlayer.PlayerGui.BuildUi

local building = false
local canPlace = true
local rotation = 90

local blocks = game.ReplicatedStorage.Blocks

local currentTemplate:BasePart = nil
local selectedBlock = blocks:WaitForChild("Plank")

local reset = false

game.UserInputService.InputBegan:Connect(function(input, processed)
	if not processed then
		if input.KeyCode == Enum.KeyCode.E then
			building = not building
			gui.Enabled = building
		end
		if input.KeyCode == Enum.KeyCode.R then
			if currentTemplate then
				rotation += 90
				if rotation == 360 then
					rotation = 0
				end
				print(rotation)
			end
		end
		if input.UserInputType == Enum.UserInputType.MouseButton1 then
			if building and canPlace then
				if not selectedBlock:IsA("Model") then
					game.ReplicatedStorage.Events.Place:FireServer(currentTemplate.Position, selectedBlock, rotation)
				else
					game.ReplicatedStorage.Events.Place:FireServer(currentTemplate.PrimaryPart.Position, selectedBlock)
				end
			end
		end
	end
end)

function round(n, to)
	return math.floor(n/to + 0.5) * to
end

for i, block:BasePart in blocks:GetChildren() do
	local newButton = gui.Container.Blocks.Scroll.Template:Clone()
	newButton.Title.Text = block.Name
	newButton.Visible = true
	newButton.Parent = gui.Container.Blocks.Scroll
	
	local function viewport()
		if not block:IsA("Model") then
			local viewBlock = block:Clone()
			viewBlock.Parent = newButton.ViewportFrame.WorldModel
			local newCam = Instance.new("Camera", newButton.ViewportFrame)
			newButton.ViewportFrame.CurrentCamera = newCam
			newCam.CFrame = workspace:WaitForChild("Viewport"):WaitForChild("CamCFrame").CFrame
			viewBlock.CFrame = workspace:WaitForChild("Viewport"):WaitForChild("Pos").CFrame

			while task.wait() do
				viewBlock.Orientation += Vector3.new(0, 0.25, 0)
			end
		else
			local viewBlock = block:Clone()
			viewBlock.Parent = newButton.ViewportFrame.WorldModel
			local newCam = Instance.new("Camera", newButton.ViewportFrame)
			newButton.ViewportFrame.CurrentCamera = newCam
			newCam.CFrame = workspace:WaitForChild("Viewport"):WaitForChild("CamCFrame").CFrame
			viewBlock:PivotTo(workspace:WaitForChild("Viewport"):WaitForChild("Pos").CFrame)

			while task.wait() do
				viewBlock:PivotTo(viewBlock:GetPivot() * CFrame.Angles(0, math.rad(0.25), 0))
			end
		end
	end
	
	coroutine.wrap(viewport)()
	
	newButton.Activated:Connect(function()
		selectedBlock = block
		reset = true
	end)
end

while task.wait() do
	repeat task.wait() until building
	reset = false
	
	if not selectedBlock:IsA("Model") then
		local blockTemplate = selectedBlock:Clone()
		blockTemplate.Transparency = 1
		blockTemplate.CanCollide = false
		local fakeTemplate = selectedBlock:Clone()
		fakeTemplate.Transparency = 0.5
		fakeTemplate.CanCollide = false

		blockTemplate.Parent = workspace
		fakeTemplate.Parent = workspace

		repeat
			local whitelist = {workspace.Baseplate, workspace.Blocks}
			local mouse = game.Players.LocalPlayer:GetMouse()
			local unitRay = cam:ScreenPointToRay(mouse.X, mouse.Y)
			local params = RaycastParams.new()

			params.FilterType = Enum.RaycastFilterType.Include
			params.FilterDescendantsInstances = whitelist

			local result = workspace:Raycast(unitRay.Origin, unitRay.Direction * 1000, params)

			if result and result.Position then
				local roundTo = 1
				local pos = Vector3.new(round(result.Position.X, roundTo), round(result.Position.Y, roundTo), round(result.Position.Z, roundTo))
				local normal = result.Normal
				local normalized = Vector3.new(normal.X * blockTemplate.Size.X / 2, normal.Y * blockTemplate.Size.Y / 2, normal.Z * blockTemplate.Size.Z / 2)
				--blockTemplate.Position = 
				currentTemplate = blockTemplate
				--fakeTemplate.Orientation = 
				blockTemplate.Orientation = Vector3.new(0, rotation, 0)
				--print(result.Position)
				blockTemplate.Position = pos + normalized
				local tween = game.TweenService:Create(fakeTemplate, TweenInfo.new(0.1, Enum.EasingStyle.Quad, Enum.EasingDirection.Out, 0, false, 0), {
					["Position"] = pos + normalized,
					["Orientation"] = Vector3.new(0, rotation, 0)
				})
				tween:Play()
			end
			task.wait()
		until not building or reset

		blockTemplate:Destroy()
		fakeTemplate:Destroy()
	else
		local blockTemplate:Model = selectedBlock:Clone()
		for i,v in blockTemplate:GetDescendants() do
			if v:IsA("BasePart") and v.Transparency ~= 1 then
				v.Transparency = 1
				v.CanCollide = false
			end
			if v:IsA("Decal") then
				v.Transparency = 1
			end
			if v:IsA("BasePart") then
				v.CanCollide = false
			end
		end
		local fakeTemplate = selectedBlock:Clone()
		for i,v in fakeTemplate:GetChildren() do
			if v:IsA("BasePart") and v.Transparency ~= 1 then
				v.Transparency = 0.5
				--v.Anchored = false
			end
			if v:IsA("BasePart") then
				v.CanCollide = false
			end
		end

		blockTemplate.Parent = workspace
		fakeTemplate.Parent = workspace
		
		currentTemplate = blockTemplate

		repeat
			local whitelist = {workspace.Baseplate, workspace.Blocks}
			local mouse = game.Players.LocalPlayer:GetMouse()
			local unitRay = cam:ScreenPointToRay(mouse.X, mouse.Y)
			local params = RaycastParams.new()

			params.FilterType = Enum.RaycastFilterType.Include
			params.FilterDescendantsInstances = whitelist

			local result = workspace:Raycast(unitRay.Origin, unitRay.Direction * 1000, params)

			if result and result.Position then
				local roundTo = 1
				local pos = Vector3.new(round(result.Position.X, roundTo), round(result.Position.Y, roundTo), round(result.Position.Z, roundTo))
				local normal = result.Normal
				--local normalized = Vector3.new(normal.X * blockTemplate.Size.X / 2, normal.Y * blockTemplate.Size.Y / 2, normal.Z * blockTemplate.Size.Z / 2)
				--blockTemplate.Position = 
				currentTemplate = blockTemplate
				--print(result.Position)
				local tween = game.TweenService:Create(fakeTemplate.PrimaryPart, TweenInfo.new(0.1, Enum.EasingStyle.Quad, Enum.EasingDirection.Out, 0, false, 0), {
					["Position"] = pos + normal
				})
				tween:Play()
				blockTemplate:PivotTo(CFrame.new(pos + normal))
				--[[local tween = game.TweenService:Create(fakeTemplate, TweenInfo.new(0.1, Enum.EasingStyle.Quad, Enum.EasingDirection.Out, 0, false, 0), {
					["Position"] = pos + normalized
				})
				tween:Play()]]
			end
			task.wait()
		until not building or reset

		blockTemplate:Destroy()
		fakeTemplate:Destroy()
	end
end

I don’t believe I need to add the server script as it doesn’t relate to the problem.

Share your code so we can help :expressionless:

2 Likes

Hello there!

Not sure if I have the solution but i’ll try to help

Are you tweening the orientation? or is it the CFrame?

If i remembered, orientation goes from - 180 to 180, so making the value go past that number may be causing the problem.

If you’re using CFrames, maybe using quaternions should help, but it’s kinda confusing to learn using them.

If you could send the piece of code that’s rotating the part it would help!

1 Like

Wrote this when I was tired this morning and it didn’t cross my mind to actually send my code, I’ll edit my post.

It tweens the rotation. My Current guess to the problem is that since I’m trying to tween to 270, it’s causing it to act strange (like you said). I’m not sure how to fix this.

Not only have I quit this project, but it’s pretty obvious nobody cares about it so I’m just going to mark this as the solution.

Just remove the if statement that check if the rotation is 360 set it to 0 remove it and it will work like u want except if u want it to be 0-360 not 90+ to no limit

Kinda too late. I’ll mark this anyways though.

Will i saw ur post after 1 hour release and don’t think they have to reply so fast u have to wait

As I previously stated, I quit the project due to disinterest. Also it has been several weeks since I first posted.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.