Screen overlay [open-source]

Hi all!

I’ve made a ModuleScript that you can use to make a screen overlay and have a function happen in the background. I figured since I probably wasn’t going to use it, that I’d share it here for anyone to use for free.

The way it works is that obviously, you first need to require it.

AssetID (if desired but not recommended as cannot call from LocalScripts):

104446281324863

Link to asset

The code in the LocalScript I used to create the overlay:

local screenOverlayHandler = require(game.ReplicatedStorage:WaitForChild("ClientModuleScripts").Gui.ScreenOverlayHandler)

local function setAction()
	print("Hello World!")
end

task.wait(3)
screenOverlayHandler:Create(setAction)

Here is a video of it in action, feel free to edit the code to your likings:

As you can see, the :Create() function of the ModuleScript takes in a function that is executed after the screen is completely covered. This is good for things like teleportations and cutscenes.

The only credit I’m asking for is for you to reply to this post saying so. I would like to see cool things made with this!

Any comments/ideas/feedback?

Alternative Code:

local screenOverlayHandler = {}

local TweenService = game:GetService("TweenService")
local Workspace = game:GetService("Workspace")
local cam = Workspace.CurrentCamera
local rotationThread = nil

local openInfo = TweenInfo.new(
	1.75,
	Enum.EasingStyle.Sine,
	Enum.EasingDirection.InOut,
	0,
	false,
	0
)

local particleInfo = TweenInfo.new(
	0.75,
	Enum.EasingStyle.Sine,
	Enum.EasingDirection.InOut,
	0,
	false,
	0
)

local uiCornerInfo = TweenInfo.new(
	0.25,
	Enum.EasingStyle.Quint,
	Enum.EasingDirection.In,
	0,
	false,
	0
)

local imageInfo = TweenInfo.new(
	1,
	Enum.EasingStyle.Quart,
	Enum.EasingDirection.InOut,
	0,
	false,
	0
)

local function createParticleEffects(screenGui: ScreenGui)
	if not screenGui:IsA("ScreenGui") then return end

	local activeFrames = {}
	local maxSizePercent = 0.05
	local viewportSize = cam.ViewportSize
	local sizeValue = math.ceil(math.max(viewportSize.X * maxSizePercent, viewportSize.Y * maxSizePercent))
	local frameSize = UDim2.fromOffset(sizeValue, sizeValue)

	local xFrames = math.ceil(viewportSize.X / sizeValue) + 3
	local yFrames = math.ceil(viewportSize.Y / sizeValue) + 3

	local totalWidth = xFrames * sizeValue
	local totalHeight = yFrames * sizeValue

	local startX = (viewportSize.X / 2) - ((xFrames - 2) * sizeValue / 2) - sizeValue
	local startY = (viewportSize.Y / 2) - ((yFrames - 2) * sizeValue / 2) - sizeValue

	for x = -1, xFrames do
		activeFrames[x] = {}
		for y = -1, yFrames do
			local frame = Instance.new("Frame", screenGui)
			frame.Size = frameSize
			frame.Position = UDim2.fromOffset(startX + (x * sizeValue), startY + (y * sizeValue))
			frame.BackgroundColor3 = Color3.fromRGB(0, 0, 0)
			frame.AnchorPoint = Vector2.new(0.5, 0.5)
			frame.Name = "TemporaryOverlayFrame"

			local uiCorner = Instance.new("UICorner", frame)
			uiCorner.CornerRadius = UDim.new(0, 0)

			activeFrames[x][y] = frame
		end
	end

	task.delay(0.15, function()
		local frame = screenGui:FindFirstChild("TeleportationFrame")
		if frame then
			frame:Destroy()
		end
	end)

	for x = -1, xFrames do
		task.wait(0.025)
		for y = -1, yFrames do
			local frame = activeFrames[x][y]
			local frameTween = TweenService:Create(frame, particleInfo, {Size = UDim2.fromOffset(0, 0), Transparency = 0.5})
			frameTween:Play()
			frameTween.Completed:Connect(function()
				frame:Destroy()
			end)

			local uiCorner = frame:FindFirstChildOfClass("UICorner")
			if uiCorner then
				local uiCornerTween = TweenService:Create(uiCorner, uiCornerInfo, {CornerRadius = UDim.new(0.5, 0)})
				uiCornerTween:Play()
				uiCornerTween.Completed:Connect(function()
					uiCornerTween:Destroy()
				end)
			end
		end
	end
end

function screenOverlayHandler:Create(action)
	if typeof(action) ~= "function" then return end
	
	local function getDiagonal()
		local camViewportSize = cam.ViewportSize
		return math.sqrt((camViewportSize.X ^ 2) + (camViewportSize.Y ^ 2)) * 5
	end

	local diagonal = getDiagonal()
	local targetSize = UDim2.fromOffset(diagonal, diagonal)

	local playerGui = game:GetService("Players").LocalPlayer.PlayerGui
	local screenGui = Instance.new("ScreenGui", playerGui)
	local frame = Instance.new("Frame", screenGui)
	Instance.new("UICorner", frame).CornerRadius = UDim.new(1, 0)

	screenGui.Name = "TeleportationGui"
	screenGui.IgnoreGuiInset = true

	frame.Name = "TeleportationFrame"
	frame.AnchorPoint = Vector2.new(0.5, 0.5)
	frame.Size = UDim2.fromOffset(0, 0)
	frame.BackgroundColor3 = Color3.fromRGB(0, 0, 0)
	frame.Position = UDim2.fromScale(0.5, 0.5)
	
	rotationThread = task.spawn(function()
		local image = Instance.new("ImageLabel", frame)
		image.AnchorPoint = Vector2.new(0.5, 0.5)
		image.Size = UDim2.fromOffset(0, 0)
		image.Position = UDim2.fromScale(0.5, 0.5)
		image.Image = "rbxassetid://" .. 98007758191436
		image.BackgroundTransparency = 1
		
		local maxSizePercent = 0.15
		local viewportSize = cam.ViewportSize
		local sizeValue = math.ceil(math.max(viewportSize.X * maxSizePercent, viewportSize.Y * maxSizePercent))
		
		local imageTween = TweenService:Create(image, imageInfo, {Size = UDim2.fromOffset(sizeValue, sizeValue)})
		imageTween:Play()
		imageTween.Completed:Wait()
		imageTween:Destroy()
		
		Instance.new("UIAspectRatioConstraint", image)
		
		while true do
			local imageTween = TweenService:Create(image, imageInfo, {Rotation = image.Rotation - 180})
			imageTween:Play()
			imageTween.Completed:Wait()
			imageTween:Destroy()
			print("DONE")
		end
	end)

	local frameTween = TweenService:Create(frame, openInfo, {Size = targetSize})
	frameTween:Play()
	frameTween.Completed:Wait()
	frameTween:Destroy()
	
	action()
	
	task.spawn(function()
		if rotationThread then
			task.cancel(rotationThread)
		end

		local image = frame:FindFirstChildOfClass("ImageLabel")
		if image then
			local shrinkTween = TweenService:Create(image, imageInfo, {Size = UDim2.fromOffset(0, 0), Rotation = 0})
			shrinkTween:Play()
			shrinkTween.Completed:Wait()
			image:Destroy()
		end

		createParticleEffects(screenGui)
	end)
end

return screenOverlayHandler
7 Likes

this is a huge time saver now i wont have to make my own transition effect all the time
i think maybe you could add some more customization like for example maybe add a loading screen mode so the ui stays until some function or loop finishes and then the ui gets hidden so you can make a loading screen that waits until like a certain map loads or something
also you could add some like image or text that could be on the overlay/transition ui

Yes, I’m planning on doing that and publishing it!
I just need some time. I will also be changing it a bit so it looks better

I’ve updated it with a new AssetId and video. What are your thoughts!?

it looks really cool now!
i’ll use this module whenever im making a game that needs transitions like this