How can i make GUI warp

does anyone know if it is possible to recreate this effect in roblox?

Since there isn’t any kind of perspective warping of UI elements in Roblox, best you can do is this:

  1. Use a frame that houses both the UI element and a ViewportFrame.
  2. In the ViewportFrame, you need to show a part that displays the same thing the UI element does (achieved using a SurfaceGui with the part)
  3. Have a local script that, when the mouse hovers over the frame, hides the normal ui element and displays the ViewportFrame. The script also enlarges the ViewportFrame, and rotates the part based on the mouse’s position.

When you’ve done all that, you should have a convincing version of the effect you provided. I probably will follow up more indepth.


thanks. i will go try this now

i just tried this but turns out that surface Gui’s do not render inside of Viewport’s :frowning:

1 Like

That’s incredibly disappointing. Hope that feature will appear some day. Or, we find another solution.

You can achieve this without viewport frames:
You just need a part in workspace that is constantly being positioned in front of the camera, SurfaceGui (with adornee set to the part) and a ScreenGui inside StarterGui. In the ScreenGui you will have a frame that detects where your mouse is (the frame has to be same size as the part to make that effect).

local camera = workspace.CurrentCamera
local run = game:GetService("RunService")
local uis = game:GetService("UserInputService")

local part = workspace.Part
local angle = CFrame.Angles(0,0,0)

	part.CFrame = (camera.CFrame + camera.CFrame.LookVector*6) * angle

local frame = script.Parent:WaitForChild("Frame")

local function moved()
	local mouse = uis:GetMouseLocation()
	local x = (mouse.X-frame.AbsolutePosition.X)/frame.AbsoluteSize.X - 0.5
	local y = (mouse.Y-frame.AbsolutePosition.Y)/frame.AbsoluteSize.Y - 0.7
	angle = CFrame.Angles(math.rad(y*50),math.rad(x*50),0)


	angle = CFrame.Angles(0,0,0)

This is a simple code Ive made that should make that effect (you might need to change some numbers depending on how you want it to look). Its not perfect as changing resolution changes frames size while part stays same size so you might need to resize the part depending on screen size. Ive managed to fix it a bit by adding a UIAspectRatioConstraint to the frame and setting AspectType to ScaleWithParentSize and DominantAxis to Height.

1 Like

Great work. I forgot about the adornee of SurfaceGui being able to do that.

i ended up going for a similar effect to what i original was looking for. however i used it on a different element.

here’s my rough code i used to test it (i will clean it up on final implementation):

local Item = require(game:GetService('ReplicatedStorage').Items.Knife.StockKnife)
local TweenService = game:GetService('TweenService')

local VPModel = Item.ViewingModel:Clone()
local Viewport = script.Parent.Template.Filled.ViewportFrame
VPModel.Parent = Viewport

local Cam ='Camera',Viewport)
Viewport.CurrentCamera = Cam

local MaxCameraAngleRadius = 45

local Angle =
	Cam.CFrame = VPModel.CFrame*Angle*Item.ViewingGrip
local Move

	TweenService:Create(Viewport,,Enum.EasingStyle.Quart),{Size = UDim2.fromScale(1.3,1.3)}):Play()
	Move = Move and Move:Disconnect() or Viewport.MouseMoved:Connect(function(x,y)
		local Pivot =,Viewport.AbsoluteSize.Y/2+36)
		local Rel =,y-Pivot.Y)
		local Devided =*MaxCameraAngleRadius,Rel.Y/Pivot.Y*MaxCameraAngleRadius)
		Angle = CFrame.Angles(0,math.rad(-Devided.X),math.rad(-Devided.Y))
	Angle =
	TweenService:Create(Viewport,,Enum.EasingStyle.Quart),{Size =,-14,1,-14)}):Play()

Edit: i altered the cframes a bit and managed to get it looking a bit better.

1 Like

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