Best way to rotate an object in ViewportFrame

Ok, my viewportframe displays my mesh object and even allows me to rotate it. This is all great. I want to have the object to keep rotating.

I could do it with a loop, but thought it might be cleaner if I used RotVelocity. Can’t get that idea to work.

My question is: What is the best method to rotate and object 360 degrees along the y axis forever.

Here is my code, I have to give credit to the community for getting me this far. I drop this in a GUI frame and run it.

local vf = Instance.new("ViewportFrame", script.Parent)
vf.Size = UDim2.new(1, 0, 1, 0)
vf.Position = UDim2.new(0, 0, 0, 0)
vf.BackgroundColor3 = Color3.new(1, 1, 1)
vf.BackgroundTransparency = (1)

local part = Instance.new("Part", vf)
part.Position = Vector3.new(0, 0, 0)
part.Anchored = false
part.RotVelocity = Vector3.new(0,10,0) --this is what i am trying to get to work

local specialMesh = Instance.new("SpecialMesh")
specialMesh.MeshId = "rbxassetid://346563222"
specialMesh.TextureId = "rbxassetid://346563291"
specialMesh.Scale = Vector3.new(4,4,4)
specialMesh.MeshType = Enum.MeshType.FileMesh
specialMesh.Parent = part

local camera = Instance.new("Camera", vf)
vf.CurrentCamera = camera

local cameraPosition = Vector3.new(3, 0, 2)
camera.CFrame = CFrame.new(cameraPosition, part.Position)

--[[
--sure this will work, but not very clean.
--also want it on a continuous loop.

function makeBrickMove()

for i = 0,36 do
wait(.1)
part.CFrame = CFrame.Angles(0,(math.rad(i*10)),0)
end
end

makeBrickMove()
]]

–Need to give credit to XAXA for getting me this far.

2 Likes

Please use codeblocks (wrap your code with ```) so it is easier for users to see your code and assist you.

Make sure to search up your question before asking as there is a chance someone found a solution:

The best way to rotate an object in ViewportFrame is to rotate the Camera rather the model. In addition, you only need to rotate the camera when the ViewportFrame is visible on the client’s screen.

The reason RotVelocity doesn’t work is that viewports do not have support for physics.

1 Like

Okay, well to get an infinite loop you should look to use a while loop which will run until the given condition is false.

The issue with using wait() in this scenario is that it can be unreliable and won’t wait exactly the amount of time you are specifying (it will be slightly different). This could add up and if you have multiple spinning objects then they won’t sync together over time. To keep the objects in sync together we can use tick() to determine the local time and calculate the rotation based off of it.

To smoothly loop, you can wait for RunService.RenderStepped, which will fire every frame.

Putting it all together:

-- rest of code here

local runService = game:GetService("RunService") -- get runservice before the loop
local startingTick = tick()

-- rotating mesh
while true do -- never ending loop
    local diff = tick() - startingTick -- time since loop started
    part.CFrame = CFrame.Angles(0, math.rad(diff), 0) -- rotate equal to amount of time passed
    -- part.CFrame = CFrame.Angles(0, 2*math.rad(diff), 0) <-- two times as fast
   
    -- wait a frame
    runService.RenderStepped:Wait()
end

As it has been pointed out above, it is usually better performance-wise to rotate the camera rather than the object itself. However, using this method I haven’t had any issues so I don’t think it’s mandatory, and perhaps only a small performance improvement. (?)

You could also stop rotation when the user isn’t looking at the screen as it’s unnecessary as this will improve performance by ignoring rotation when it doesn’t need to be seen.

9 Likes

The code works great. Thanks so much for your help.

local runService = game:GetService("RunService") -- get runservice before the loop
local startingTick = tick()

local vf = Instance.new("ViewportFrame", script.Parent)
vf.Size = UDim2.new(1, 0, 1, 0)
vf.Position = UDim2.new(0, 0, 0, 0)
vf.BackgroundColor3 = Color3.new(1, 1, 1)
vf.BackgroundTransparency = (1)

local part = Instance.new("Part", vf)
part.Position = Vector3.new(0, 0, 0)
part.Anchored = false

local specialMesh = Instance.new("SpecialMesh")
specialMesh.MeshId = "rbxassetid://346563222"
specialMesh.TextureId = "rbxassetid://346563291"
specialMesh.Scale = Vector3.new(4,4,4)
specialMesh.MeshType = Enum.MeshType.FileMesh
specialMesh.Parent = part


local camera = Instance.new("Camera", vf)
vf.CurrentCamera = camera

local cameraPosition = Vector3.new(3, 0, 2)
camera.CFrame = CFrame.new(cameraPosition, part.Position)

function makeBrickMove()

-- rotating mesh
	while true do -- never ending loop
   	 local diff = tick() - startingTick -- time since loop started
    	part.CFrame = CFrame.Angles(0, math.rad(diff), 0) -- rotate equal to amount of time passed
    	-- part.CFrame = CFrame.Angles(0, 2*math.rad(diff), 0) <-- two times as fast
   
   		 -- wait a frame
   		runService.RenderStepped:Wait()
	end
end

makeBrickMove()

--[[
	
--sure this will work, but not very clean.
--also want it on a continuous loop.
function makeBrickMove()
	for i = 0,36 do
		wait(.1)
		part.CFrame = CFrame.Angles(0,(math.rad(i*10)),0)
	end
end


makeBrickMove()
]]
6 Likes