UIAnimController is a small, free, and easy-to-use client-side UI utility that automatically adds nice hover and click animations to TextButton / ImageButton and simple debounced slide-in-frame toggles. Everything is scale-based and AnchorPoint-safe.

Features:
- Automatically finds and watches buttons in the player’s
PlayerGui(including cloned ones). - Hover effect (slight scale up) and click effect (shrink → bounce → return) with debounce and sound hooks.
- Frame toggling by button attribute: opens a target frame with a slide-up animation and closes any other open frame first.
- Compatible with any AnchorPoint.
- Ignores buttons whose
SizeusesOffset(works only with scale-based sizes). - Simple API:
.init(),.open_by_name(),.close_by_name() - and finally, easy customization via
script.Config.
PREVIEW:
(sry for quality, using roblox default recorder, my obs settings got messed up)
Quick install:
- Import Free Model: FROM HERE
- Place the
UIAnimControllermodule inReplicatedStorage - Create a
LocalScriptinStarterGuiORStarterPlayerScripts - Paste in these lines:
local ui = require(game.ReplicatedStorage.UIAnimController)
ui.init()
- the installing is done, but it won’t work yet, Read the USAGE bellow
How to connect buttons ⇄ frames
-
Give the target frame a unique
Name(for examplemenu_frame).
-
On the button that should toggle that frame, add an Attribute
ui_togglewith value"menu_frame"(string).
( Alternative attribute name supported:toggle_frame.) -
To make a button inside a frame close that frame, either:
- Add an Attribute
close = trueto that close button; or - Add a
BoolValuechild namedclosewithValueset totrueto the close button.*
- Notes:
- Frames slide in from the bottom (off-screen) to the frame’s stored default
Position. Size is never changed. - Buttons must use scale-only
UDim2sizes (no Offset); otherwise the button will be ignored.
at this point, you’re already done setting it up. but you can keep reading c:
API (main module):
-
module.init(player?)
Start the system. Ifplayeromitted it usesPlayers.LocalPlayer. -
module.open_by_name(name)
Finds a frame in the player GUI byName(recursive search) and opens it. -
module.close_by_name(name)
Finds a frame byNameand closes it.
(Internals are split across Manager/* - Frame and Button hold the logic. No changes needed for normal usage.)
Config / customization:
Open script/Config to change:
- hover / click scales (
hover_scale,click_shrink,click_bounce) - sound IDs (
hover_sound_id,click_sound_id) → set to"rbxassetid://<id>"strings - tween durations and easing (
tween_info_*,frame_open_time,frame_close_time)
You can change these values at edit-time or add a small wrapper to allow runtime configuration.
Limitations & Tips:
- Only supports buttons with scale-only
Size(no Offset). This was intentional to keep the position compensation simple and robust. - If you use
AutomaticSizeor UI Layouts, the script waits a couple of Heartbeats when the frame opens for the layout to settle — this avoids the first-open flash. If you still see a flash for a specific complex frame, mention its layout (AutomaticSize/UIListLayout) and I can provide a tweak. - Everything is client-side (LocalScript) — do not use for server-side UI logic.
- AnchorPoint: fully supported (script compensates for AnchorPoint so visual center doesn’t jump).

