[HELP] How can I make a 3D Button Effect? Please

how to make a 3d button animation like this one?

2 Likes

Video does not seem to load for me; could you attach an image example instead?

1 Like

The video should work now :smiley: (I HOPE)

That’s pretty simple.
Have the image at the bottom and set the anchor point to something like Vector2.new(0.5,1) (of the top image)
Then move it up slightly and scale it up upon hovering.

1 Like

But thats the problem, the button isnt a image, I managed to contact with the game dev and he gave me some ui elements including that CODES gui


the holder frame is the frame thats actually containing the texts and effects, but the main background which is the button redeem is the darksh background behind the holder

So what ur telling me to do, setting the anchor point of the holder to 0.5,1 or the main frame that holding it

(ignore the uiaspectratio i can remove it if it will conflict with anything)

You can look at the source code of my plugin if you want; I implemented something similar.

local a = game:GetObjects("rbxassetid://91144332656693")[1] a.Parent = workspace print(a)

You basically have a frame at the bottom that is fully static and a top image covering it for the illusion to work.
Adding a little UIStroke covers the imperfections.
Not sure about the scaling part; my example simply moves it, but to make it cartoony and exaggerated, you may experiment with it as well.

1 Like

I have been trying for so long and it doesnt work for my button structure, And I got ur plugins code and extracted the button effect and modifed it to work with my button structure and still it doesnt look good or either working

thanks for ur help tho have a great day :smiley:

Care to extract part of your ui with the button into a sample project and share this file here so people can be more specific?
Thank you!

1 Like

redeem_button.rbxm (13.0 KB)
Here, please someone help me :frowning:

One way to do it..

edit: Updated. See current version in this comment.


Gui Kit Menu.rbxm (17.9 KB)

You can use this standart kit

ALL OF THE SCRIPTS HAVE HELPING SIGNS IN CASE YOU HAVE A QUESTION

For do this:
Create a frame inside your button and set it to the color you want. Make the frame’s height around 90–95% of the button’s total height.
After this set the color of button to be darker than the frame color.
Then create a tween. (when the user clicks the button, make the frame’s height increase to 100%)
You can also add additional a tween for the size like in your video.

Here a exemple:
Exemple.rbxm (9.8 KB)

Previous my post has been updated:

  • added tween animations
  • durations of animations are variable and depend on previously traveled path: for example:
    – let’s assume hover animation takes 1 second
    – user removes mouse before hover animation has ended, let’s assume on its half way
    – so we need to put button back in regular state also with animation but its duration should be .5 seconds
  • updated checker style tiling so it looks properly zoomed
  • edit: removed redundant variables, fixed scenario: press button and move mouse away - button remains pressed

Interaction with mouse looks this way:

Interaction with touch devices:
Interesting thing that touch has no “hover” concept but Roblox simulates it:
– both hover and press play at the same time


Which I suspect does not look as expected so that that was fixed as “do not play hover” if “mouse entered” received after “mouse pressed”:

  • no animation for mouse enter

The code (LocalScript as a child of Redeem frame)
--!strict
local tween_service = game:GetService("TweenService")

local redeem_frame = script.Parent

type playback_direction = "forward" | "backward"

type tween_wrapper = {
	number_value : NumberValue;
	duration : number;
	play : (self : tween_wrapper, playback_direction : playback_direction) -> ();
	tween : Tween?;
	is_playing : (self : tween_wrapper) -> boolean;
}

local function play(self : tween_wrapper, playback_direction : playback_direction) : ()
	local start_value = self.number_value.Value
	assert(playback_direction == "forward" or playback_direction == "backward", "unexpected playback_direction[" .. tostring(playback_direction) .. "]")
	local goal = playback_direction == "forward" and 1 or 0
	if start_value == goal then return end
	local distance = math.abs(goal - start_value)
	local duration = self.duration * distance
	self.tween = tween_service:Create(self.number_value, TweenInfo.new(duration), { Value = goal })
	if not self.tween then error("tween is nil") return end
	self.tween:Play()
	self.tween.Completed:Wait()
	self.tween = nil
end

local function is_playing(self : tween_wrapper) : boolean
	return nil ~= self.tween
end

local function create_tween_wrapper(duration : number, value_handler : (value : number) -> ()) : tween_wrapper
	local result = {
		number_value = Instance.new("NumberValue");
		duration = duration;
		play = play;
		is_playing = is_playing;
	}
	
	result.number_value.Value = 0
	result.number_value.Changed:Connect(value_handler)

	return result
end

local hover_offset = 20
local hover_size_diff = UDim2.new(0, hover_offset, 0, hover_offset)
local hover_animation_duration = .1
local pressed_offset = 8
local pressed_position_diff = UDim2.new(0, 0, 0, pressed_offset)
local pressed_animation_duration = .1

local original_size : UDim2? = nil
local original_position : UDim2? = nil

local tile = redeem_frame:WaitForChild("Holder"):WaitForChild("Tile")
local tile_frame_absolute_size = tile.AbsoluteSize
local tile_frame_tile_size = tile.TileSize
local hover_tween_wrapper = create_tween_wrapper(hover_animation_duration
	, function(value : number)
		if not original_size then error("original_size is nil") end
		redeem_frame.Size = original_size:Lerp(original_size + hover_size_diff, value)
		-- scale tile size
		assert(tile_frame_tile_size.X.Scale == 0 and tile_frame_tile_size.Y.Scale == 0) -- the logic below must be updated since it assumes zero scales
		local tile_frame_current_size = tile.AbsoluteSize
		local scale_x = tile_frame_current_size.X / tile_frame_absolute_size.X
		local scale_y = tile_frame_current_size.Y / tile_frame_absolute_size.y
		tile.TileSize = UDim2.new(0, tile_frame_tile_size.X.Offset * scale_x, 0, tile_frame_tile_size.Y.Offset * scale_y)
	end
)

local pressed_tween_wrapper = create_tween_wrapper(pressed_animation_duration
	, function(value : number)
		if not original_position then error("original_position is nil") end
		redeem_frame.Position = original_position:Lerp(original_position + pressed_position_diff, value)
	end
)

redeem_frame.MouseEnter:Connect(function()
	local previous_size = redeem_frame.Size
	if not original_size then original_size = previous_size end
	-- touch devices receive MouseEnter after MouseButton1Down
	-- do not play hover animations in such cases
	if pressed_tween_wrapper:is_playing() then return end
	hover_tween_wrapper:play("forward")
end)

redeem_frame.MouseLeave:Connect(function()
	if not original_size then return end
	hover_tween_wrapper:play("backward")
	-- fixes scenario: press button and while pressed move mouse pointer away
	-- helps touch devices also
	pressed_tween_wrapper:play("backward") 
end)

local text_button = redeem_frame:WaitForChild("TextButton")
text_button.MouseButton1Down:Connect(function()
	local previous_position = redeem_frame.Position
	if not original_position then original_position = previous_position end
	pressed_tween_wrapper:play("forward")
end)

text_button.MouseButton1Up:Connect(function()
	if not original_position then return end
	pressed_tween_wrapper:play("backward")
end)
1 Like