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.