UI Parallax via Mouse Movement

Hello everyone! This tutorial on a pretty basic approach for creating a parallax effect in your UI. Beginner to intermediate programming skills are recommended so you can understand the code but not required at all. Here’s a quick demo of what we’ll be making:


First things first, we make a ScreenGui object. Create a container frame to put all your moving images in with the property “ClipsDescendants” ticked underneath the ScreenGui.
Hierarchy


Next, as you probably saw, we’re going to be making a script somewhere under the ScreenGui.
I kept it out of the container folder just because of convenience but you could just as well have it underneath anything. Inside this script we’re going to be doing the entire effect. First, let’s start off with a reference to our container frame and a lerp function.

local container	= script.Parent.container
local function lerp(a, b, t)
	return a * (1 - t) + b * t
end

Next we’re going to make a variable called “focus” and a table called “movers”. Inside this table we’ll make another table for each of the frames we want to move. These sub tables will contain the frame instance, it’s original position, and a “distance” number. This distance number and the focus number will tell the code how to pan each frame properly.

local focus		= 10
local movers	= {
	{container.background, container.background.Position, 20},
	{container.text, container.text.Position, 15},
	{container.character, container.character.Position, 5},
}

Now on to the fun part, math! We’re going to make 2 new variables here set to zero: “x” and “y”. These will be what the mouse’s movements are. Right after that, go ahead and access the Run service built into Roblox and hook it to a function with a “dt” argument for our lerp in the future.

local x, y = 0, 0
game:GetService("RunService").RenderStepped:Connect(function(dt)
	
end)

Next, create a “mouse” variable and set x and y to a lerp from themselves, to the target position of the mouse. This lerp will smooth the movement of the UI elements.

game:GetService("RunService").RenderStepped:Connect(function(dt)
	local mouse	= game.Players.LocalPlayer:GetMouse()
	x = lerp(x, mouse.X * 0.01, dt)
	y = lerp(y, mouse.Y * 0.01, dt)
end)

Lastly, loop through all the tables in the “movers” table and apply the result of the lerps. The key behind this effect is the v[3] - focus acting as a modifier of the axis. This basically scales the mouse movement by the distance the frame should be from the focus point, going negative when the mover is in front of the focus point and reaching larger numbers when the distance from the focus is far.

game:GetService("RunService").RenderStepped:Connect(function(dt)
	local mouse	= game.Players.LocalPlayer:GetMouse()
	x = lerp(x, mouse.X * 0.01, dt)
	y = lerp(y, mouse.Y * 0.01, dt)
	
	for _, v in pairs(movers) do
		v[1].Position	= UDim2.new(
			v[2].X.Scale,
			v[2].X.Offset + (x * (v[3] - focus)),
			v[2].Y.Scale,
			v[2].Y.Offset + (y * (v[3] - focus))
		)
	end
end)

All in all, a neat looking effect with some really cool and easy math involved. If you have any other information that I left out then be sure to let me know in the replies.
Thanks for reading!

Place file:
parallax.rbxl (53.7 KB)

32 Likes

Honestly, you shouldn’t:

  1. Grab the mouse inside of the RenderStepped instead of making it a variable on top.
  2. Use player:GetMouse() at all, use the UserInputService for this instead.

Other than this, neat tutorial!

4 Likes

Good tutorial! Vouch (30 :frowning: )

Do you think you could explain how/why this works? I’m trying to understand and I just can’t…