Feedback on GUI + Scripts

Hello! I made this gui for the sake of having a menu with a character creation sub-menu.

Other than the fact that most of the code looks sloppy and unorganized, and the color theory within the GUI is ugly and non-existent, is there anything better I could be doing? Both scripting AND ui design wise (Except for the color, I couldn’t think of anything better.)

Any and all feedback is appreciated as the assets are listed below. Sorry if it is hard to read, my eyes are weird </3


Video Preview:

Link to uncopylocked game:


Gui Structure

Scripts Related
Town Hall Script
local Replicated_Storage = game:GetService("ReplicatedStorage")
local Server_Script_Service = game:GetService("ServerScriptService")
local Tween_Service = game:GetService("TweenService")

local CharacterCreationModule = require(Server_Script_Service.CharacterCreationModule)

local Events_Folder = Replicated_Storage:WaitForChild("Events")
local CorrectUserIdEvent = Events_Folder:WaitForChild("CorrectUserId")

local Town_Hall_Model = script.Parent
local Interaction_Part = Town_Hall_Model.Entrance.Interaction_Part
local Proximity_Prompt = Interaction_Part.ProximityPrompt

local Guis_Folder = Replicated_Storage:WaitForChild("Guis_Folder")
local Cutscene_Gui = nil
local Confirmation_Gui = Guis_Folder:WaitForChild("Confirmation_GUI")
local Town_Hall_Gui = Guis_Folder:WaitForChild("TownHallGUI")

local ti = TweenInfo.new(
	1,
	Enum.EasingStyle.Quad,
	Enum.EasingDirection.InOut,
	0,
	false,
	0
)

local Connections = {
	["Confirmation"] = {},
	["CreateNewCharacter"] = {}
}

local function Disconnect(Type: string)
	for i, v in pairs(Connections[Type]) do
		v:Disconnect()
	end
end

local function ExitTownHallGui(Player:Player, GuiToDelete:Instance)
	local PlayerGui = Player:FindFirstChild("PlayerGui")
	Tween_Service:Create( --Show's the options to enter a UserId, or use current character.
		GuiToDelete:FindFirstChild("Background"),
		ti,
		{ Position = UDim2.new(0.5, 0, 2, 0) }
	):Play()
	wait(1)
	GuiToDelete:Destroy()
end

local function TownHall_Logic(Player:Player)
	local PlayerGui = Player:FindFirstChild("PlayerGui")

	local TownHall_GuiClone

	if PlayerGui:FindFirstChild("TownHallGUI") ~= nil then
		TownHall_GuiClone = PlayerGui:FindFirstChild("TownHallGUI")
		TownHall_GuiClone:FindFirstChild("Background").Position = UDim2.new(0.5, 0, 2, 0)

		Tween_Service:Create( --Show's the options to enter a UserId, or use current character.
			TownHall_GuiClone:FindFirstChild("Background"),
			ti,
			{ Position = UDim2.new(0.5, 0, 0.5, 0) }
		):Play()
	elseif not PlayerGui:FindFirstChild("TownHallGUI") then
		TownHall_GuiClone = Town_Hall_Gui:Clone()
		TownHall_GuiClone:FindFirstChild("Background").Position = UDim2.new(0.5, 0, 2, 0)

		Tween_Service:Create( --Show's the options to enter a UserId, or use current character.
			TownHall_GuiClone:FindFirstChild("Background"),
			ti,
			{ Position = UDim2.new(0.5, 0, 0.5, 0) }
		):Play()

	end

	local Background = TownHall_GuiClone:FindFirstChild("Background")
	local ExitButton = Background:FindFirstChild("ExitButton")
	local Menu = Background:FindFirstChild("Menu")
	local Features_Folder = Menu:FindFirstChild("Features")

	local Buttons_Folder = Menu:FindFirstChild("Buttons")
	local CNC_Background = Features_Folder:FindFirstChild("CreateNewCharacter")


	TownHall_GuiClone.Parent = PlayerGui

	Buttons_Folder.CreateNewCharacter.Clickable.MouseButton1Click:Connect(function(...)

		print("Clicked Create New Character")

		--< Fade out all of the buttons.
		for _, Button in pairs(Buttons_Folder:GetChildren()) do
			if Button:IsA("CanvasGroup") then
				print(Button)
				Button.Visible = false
			end
		end

		CNC_Background.Visible = true
		wait(1)
		Tween_Service:Create( --Show's the options to enter a UserId, or use current character.
			CNC_Background,
			ti,
			{ Position = UDim2.new(0.5, 0, 0.5, 0) }
		):Play()
	end)

	CNC_Background.EnterUserId.MouseButton1Click:Connect(function(...)
		print(Player, "Clicked Enter UserId")
		Tween_Service:Create(
			CNC_Background,
			ti,
			{ Position = UDim2.new(0.5, 0, 2, 0) }
		):Play()
		wait(1)
		CNC_Background.Visible = false
		--< Disconnect("CreateNewCharacter")
		--< Tween down the CNC_Background
		--< Tween up the TextBox GUI

		local UserIdTextBox = Features_Folder:WaitForChild("UserIdTextBox")

		UserIdTextBox.Visible = true

		Tween_Service:Create(
			UserIdTextBox,
			ti,
			{ Position = UDim2.new(0.5, 0, 0.5, 0) }
		):Play()

		print(UserIdTextBox)
	end)

	CNC_Background.UseCurrentOutfit.MouseButton1Click:Connect(function(...)
		if not Player then warn("No player detected"); return end
		print(Player, "Clicked Use Current Outfit")
		local Character = Player.Character
		if not Character then warn("Character not found"); return end
		print(Character)
		local HumanoidDescription = Character:FindFirstChild("Humanoid"):FindFirstChild("HumanoidDescription")
		print(HumanoidDescription)
		if not HumanoidDescription then warn("Humanoid or Humanoid Description not found"); return end

		local new = CharacterCreationModule:CreateRigFromHumanoidDescription(HumanoidDescription, workspace, CFrame.new(28.6, 5.5, -9))
		if new then
			Tween_Service:Create(
				CNC_Background,
				ti,
				{ Position = UDim2.new(0.5, 0, 2, 0) }
			):Play()
			Player.PlayerGui:WaitForChild("TownHallGUI"):WaitForChild("Background"):WaitForChild("Menu"):WaitForChild("Buttons"):WaitForChild("CreateNewCharacter").Visible = true
			wait(0.25)
			Tween_Service:Create( --Show's the options to enter a UserId, or use current character.
				Player.PlayerGui:WaitForChild("TownHallGUI"):WaitForChild("Background"):WaitForChild("Menu"):WaitForChild("Buttons"):WaitForChild("CreateNewCharacter"),
				ti,
				{ Position = UDim2.new(0.189, 0, 0.207, 0) }
			):Play()
		end
	end)

	ExitButton.MouseButton1Click:Connect(function(...)

		print(Player, "Exit Click!")
		ExitTownHallGui(Player, TownHall_GuiClone)		
	end)
end

local function Show_Confirmation_Popup(Player:Player)
	local PlayerGui = Player:FindFirstChild("PlayerGui")
	local Confirmation = Confirmation_Gui:Clone()
	Confirmation.Background.Location_Text.Text = "Town Hall"
	Confirmation.Background.Position = UDim2.new(0.5, 0, 2, 0) --< Bottom Center off of the screen

	Tween_Service:Create(
		Confirmation.Background, --< Animates the background
		ti,
		{ Position = UDim2.new(0.5, 0, 0.5, 0) }
	):Play()

	local yesConnection = table.insert(Connections.Confirmation, Confirmation.Background.Yes.MouseButton1Click:Connect(function()
		Disconnect("Confirmation")
		print("Yes")

		Tween_Service:Create(
			Confirmation.Background, --< Animates the background
			ti,
			{ Position = UDim2.new(0.5, 0, 2, 0) }
		):Play()
		wait(1)
		Confirmation:Destroy() --< Destroys the ScreenGui Object

		TownHall_Logic(Player)
	end))

	local noConnection = table.insert(Connections.Confirmation, Confirmation.Background.No.MouseButton1Click:Connect(function()
		Disconnect("Confirmation")

		print("No")

		Tween_Service:Create(
			Confirmation.Background, --< Animates the background
			ti,
			{ Position = UDim2.new(0.5, 0, 2, 0) }
		):Play()
		wait(1)
		Confirmation:Destroy()
	end))

	Confirmation.Parent = PlayerGui
end

local function Test(Player:Player)
	print(Player.Name .. " has initiated the Test")
	Show_Confirmation_Popup(Player)
end

Proximity_Prompt.Triggered:Connect(Test)

--CharacterCreationModule:CreateRigFromUserId(128160667, workspace, CFrame.new(28.6, 5.5, -9))
--CharacterCreationModule:CreateRigFromHumanoidDescription(128160667, workspace, CFrame.new(14.6, 5.5, -9))

CorrectUserIdEvent.OnServerEvent:Connect(function(Player:Player, UserId:number, Element:Instance)
	print(Player, UserId)
	if not UserId then warn("No UserId Provided"); return end

	Tween_Service:Create(
		Element,
		ti,
		{Position = UDim2.new(0.5, 0, 2, 0)}
	):Play()
	wait(1)
	Element.Visible = false

	CharacterCreationModule:CreateRigFromUserId(UserId, workspace, CFrame.new(28.6, 5.5, -9))
	Player.PlayerGui:WaitForChild("TownHallGUI"):WaitForChild("Background"):WaitForChild("Menu"):WaitForChild("Features"):WaitForChild("CreateNewCharacter").Visible = true
	Player.PlayerGui:WaitForChild("TownHallGUI"):WaitForChild("Background"):WaitForChild("Menu"):WaitForChild("Buttons"):WaitForChild("CreateNewCharacter").Visible = true
	wait(0.25)
	Tween_Service:Create( --Show's the options to enter a UserId, or use current character.
		Player.PlayerGui:WaitForChild("TownHallGUI"):WaitForChild("Background"):WaitForChild("Menu"):WaitForChild("Buttons"):WaitForChild("CreateNewCharacter"),
		ti,
		{ Position = UDim2.new(0.189, 0, 0.207, 0) }
	):Play()
end)

Character Creation Module Script

Located in Server Script Service

--!nocheck
--< Services >--
local Players_Service = game:GetService("Players")
--< Modules >--

--< Variables >--
local CharacterCreationModule = {}
CharacterCreationModule.__index = CharacterCreationModule

--< Functions >--

--[[
Creates a new R6 only model rig with the given UserId, parents the rig to the "Parent" parameter, and then returns the rig as a variable for further use.
-----------------------------------------------------------------------------------------------------------------------------------------------
]]
function CharacterCreationModule:CreateRigFromUserId(
	UserId : number,
	Parent : Instance?,
	CFramePosition : CFrame
): Model
	if not UserId then warn("UserId is nil."); return end
	if not Parent then warn("You did not set the parent parameter."); return end
	if not CFramePosition then warn("No position has been set."); return end
	
	local NewRig = Players_Service:CreateHumanoidModelFromUserId(UserId)
	NewRig.PrimaryPart:PivotTo(CFramePosition)
	NewRig.Parent = Parent
	
	return NewRig
end

--[[
Creates a new R6 and/or R15 model rig with the given UserId and retrieves a HumanoidDescription, parents the rig to the "Parent" parameter, and then returns the rig as a variable for further use.
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
]]
function CharacterCreationModule:CreateRigFromUserIdToHumanoidDescription(
	UserId : number,
	Parent : Instance?,
	CFramePosition : CFrame
):Model
	if not UserId then warn("UserId is nil."); return end
	if not Parent then warn("You did not set the parent parameter."); return end
	if not CFramePosition then warn("No position has been set."); return end
	
	local HumanoidDescriptionFromUserId = Players_Service:GetHumanoidDescriptionFromUserId(UserId)
	local NewRig = Players_Service:CreateHumanoidModelFromDescription(HumanoidDescriptionFromUserId, Enum.HumanoidRigType.R15)
	NewRig.PrimaryPart:PivotTo(CFramePosition)
	NewRig.Parent = Parent
	
	return NewRig
end

--[[
Creates a new R6 and/or R15 model rig with the given HumanoidDescription, parents the rig to the "Parent" parameter, and then returns the rig as a variable for further use.
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
]]
function CharacterCreationModule:CreateRigFromHumanoidDescription(
	HumanoidDescription : HumanoidDescription,
	Parent : Instance?,
	CFramePosition : CFrame
):Model
	if not HumanoidDescription then warn("HumanoidDescription is nil."); return end
	if not Parent then warn("You did not set the parent parameter."); return end
	if not CFramePosition then warn("No position has been set."); return end

	local NewRig = Players_Service:CreateHumanoidModelFromDescription(HumanoidDescription, Enum.HumanoidRigType.R15)
	NewRig.PrimaryPart:PivotTo(CFramePosition)
	NewRig.Parent = Parent

	return NewRig
end

--< Connections >--
return CharacterCreationModule

UIFX Module Script

I just want to give a quick thank you to @AltaccVedoxxx00 for creating the Module Script (UIFX - Animation Module) and @KingBlueDash for modifying it to function better (UIFX - Animation Module - #4 by KingBlueDash)

local SoundService = game:GetService("SoundService")
local TweenService = game:GetService("TweenService")

local HoveringSound = SoundService:FindFirstChild("HoveringSound")
local ClickingSound = SoundService:FindFirstChild("ClickingSound")

local UIFX = {}
UIFX.__index = UIFX

type tab = {[any]: any}

function UIFX:HoverBigger(
	Element: GuiButton,
	Size: UDim2,
	SwapsColors: boolean,
	Rotates: boolean,
	Threshold: {any},
	Duration: number,
	Style: Enum.EasingStyle,
	Direction: Enum.EasingDirection,
	AddToAConnectionsTable: {boolean | tab}
)

	local OriginalSize = Element.Size
	local OriginalBGColor = Element.BackgroundColor3
	local OriginalRotation = Element.Rotation
	local OriginalTextColor, OriginalImageColor, OriginalIconImageColor, Icon

	if Element:FindFirstChild("Icon") then
		Icon = Element:FindFirstChild("Icon")
		OriginalIconImageColor = Icon.ImageColor3
	end

	if Element:IsA("TextButton") or Element:IsA("TextBox") then
		OriginalTextColor = Element.TextColor3
	elseif Element:IsA("ImageButton") then
		OriginalTextColor = nil
		OriginalImageColor = Element.ImageColor3
	end

	local function OnMouseEnter()
		task.wait(.0125)

		if HoveringSound then
			HoveringSound:Play()
		end

		local SwappedColorAmount

		if Threshold then
			if Threshold[3] then
				SwappedColorAmount = Threshold[3]
			else
				SwappedColorAmount = 1
			end
		end

		TweenService:Create(
			Element,
			TweenInfo.new(Duration, Style, Direction),
			{Size =
				UDim2.new(
					OriginalSize.X.Scale + Size.X.Scale,
					OriginalSize.X.Offset + Size.X.Offset,
					OriginalSize.Y.Scale + Size.Y.Scale,
					OriginalSize.Y.Offset + Size.Y.Offset
				),
				Rotation = (Rotates and math.random(Threshold[1], Threshold[2]) or OriginalRotation)
			}
		):Play()

		if SwapsColors then

			local InvertedBGColor3 = Color3.new(
				SwappedColorAmount - Element.BackgroundColor3.R,
				SwappedColorAmount - Element.BackgroundColor3.G,
				SwappedColorAmount - Element.BackgroundColor3.B
			)

			local InvertedTextColor3, InvertedImageColor3

			if Element:IsA("TextButton") or Element:IsA("TextBox") then

				InvertedTextColor3 = Color3.new(
					SwappedColorAmount - Element.TextColor3.R,
					SwappedColorAmount - Element.TextColor3.G,
					SwappedColorAmount - Element.TextColor3.B
				)

				TweenService:Create(
					Element,
					TweenInfo.new(Duration * 1.75, Style, Direction),
					{TextColor3 = InvertedTextColor3, BackgroundColor3 = InvertedBGColor3}
				):Play()

			elseif Element:IsA("ImageButton") then

				InvertedImageColor3 = Color3.new(
					SwappedColorAmount - Element.ImageColor3.R,
					SwappedColorAmount - Element.ImageColor3.G,
					SwappedColorAmount - Element.ImageColor3.B
				)

				TweenService:Create(
					Element,
					TweenInfo.new(Duration * 1.75, Style, Direction),
					{BackgroundColor3 = InvertedBGColor3, ImageColor3 = InvertedImageColor3}
				):Play()

			end

		end

	end

	local function OnMouseLeave()

		task.wait(.0125)

		TweenService:Create(
			Element,
			TweenInfo.new(Duration, Style, Direction),
			{Size = OriginalSize, Rotation = OriginalRotation}
		):Play()

		if SwapsColors then

			if Element:IsA("TextButton") or Element:IsA("TextBox") then

				TweenService:Create(
					Element,
					TweenInfo.new(Duration * 1.75, Style, Direction),
					{BackgroundColor3 = OriginalBGColor, TextColor3 = OriginalTextColor}
				):Play()

			elseif Element:IsA("ImageButton") then

				TweenService:Create(
					Element,
					TweenInfo.new(Duration * 1.75, Style, Direction),
					{BackgroundColor3 = OriginalBGColor, ImageColor3 = OriginalImageColor}
				):Play()

			end

		end

	end

	local EnterConnection

	local LeaveConnection

	EnterConnection = Element.MouseEnter:Connect(OnMouseEnter)

	LeaveConnection = Element.MouseLeave:Connect(OnMouseLeave)

	local function StopFunction()

		OnMouseLeave()

		EnterConnection:Disconnect()

		LeaveConnection:Disconnect()

		if Element:FindFirstChild("__uiFXMouseEntered") then
			Element:FindFirstChild("__uiFXMouseEntered"):Destroy()
		end

		if Element:FindFirstChild("__uiFXMouseLeft") then
			Element:FindFirstChild("__uiFXMouseLeft"):Destroy()
		end

	end

	if AddToAConnectionsTable[1] and AddToAConnectionsTable[2] then
		table.insert(AddToAConnectionsTable[2], StopFunction)
	else
		return StopFunction
	end

end

function UIFX:ButtonPress(
	Element: GuiButton,
	Size: UDim2,
	Rotates: boolean,
	Threshold: {any},
	Duration: number,
	Style: Enum.EasingStyle,
	Direction: Enum.EasingDirection,
	AddToAConnectionsTable: {boolean | tab}
)

	local OriginalSize = Element.Size

	local OriginalRotation = Element.Rotation

	local function OnMouseDown()

		if ClickingSound then
			ClickingSound:Play()
		end

		TweenService:Create(
			Element,
			TweenInfo.new(Duration, Style, Direction),
			{
				Size = UDim2.new(
					OriginalSize.X.Scale + Size.X.Scale,
					OriginalSize.X.Offset + Size.X.Offset,
					OriginalSize.Y.Scale + Size.Y.Scale,
					OriginalSize.Y.Offset + Size.Y.Offset
				),
				Rotation = (Rotates and math.random(Threshold[1], Threshold[2]) or OriginalRotation)
			}
		):Play()

	end

	local function OnMouseUp()

		TweenService:Create(
			Element,
			TweenInfo.new(Duration, Style, Direction),
			{Size = OriginalSize, Rotation = OriginalRotation}
		):Play()

	end

	local EnterConnection

	local LeaveConnection

	if Element:IsA("CanvasGroup") then
		--print(tostring(Element) .. " is a CanvasGroup")
		EnterConnection = Element.Clickable.MouseButton1Down:Connect(function()
			OnMouseDown()
		end)

		LeaveConnection = Element.Clickable.MouseButton1Up:Connect(function()
			OnMouseUp()
		end)
	else
		EnterConnection = Element.MouseButton1Down:Connect(function()
			OnMouseDown()
		end)

		LeaveConnection = Element.MouseButton1Up:Connect(function()
			OnMouseUp()
		end)
	end

	local function StopFunction()

		OnMouseUp()

		EnterConnection:Disconnect()

		LeaveConnection:Disconnect()

	end

	if AddToAConnectionsTable[1]  and AddToAConnectionsTable[2] then
		table.insert(AddToAConnectionsTable[2], StopFunction)
	else
		return StopFunction
	end

end

return UIFX

Local Script located inside of the TextBox named UserIdTextBox

This script just makes sure that only a number (0-9) is entered, and wont return true if anything other than a number was entered.

local Replicated_Storage = game:GetService("ReplicatedStorage")
local Events_Folder = Replicated_Storage:WaitForChild("Events")

local CorrectUserIdEvent = Events_Folder:WaitForChild("CorrectUserId")

-- Get the Textbox object
local textBox = script.Parent

-- Function to validate user input
local function validateInput(input:string) :boolean
	-- Check if the input is empty
	if input == "" then
		return false
	end

	-- Check if the input contains non-numeric or non-decimal characters
	if string.match(input, "[^%d]") then
		return false
	end

	return true
end

local colorNormal = Color3.new(1, 1, 1) -- white
local colorWrong = Color3.new(1, 0, 0) -- red
local colorCorrect = Color3.new(0, 1, 0) -- green

-- Function to handle user input
local function handleInput()
	local input = textBox.Text
	if not validateInput(input) then
		textBox.Text = "" --Custom text for invalid entry 
		--Executes when there is not valid input
		textBox.BackgroundColor3 = colorNormal
		print("False")
	else
		--Executes when there is valid input
		textBox.BackgroundColor3 = colorCorrect
		textBox.Text = "Loading Character..."
		print("True")
		wait(1)
		CorrectUserIdEvent:FireServer(input, textBox)
		textBox.BackgroundColor3 = colorNormal
		textBox.Text = "Done!"
		wait(0.5)
		textBox.Text = ""
	end
end

-- Connect the handleInput function to the TextBox object's events
textBox.Focused:Connect(function()
	-- Clear the Textbox when the user focuses on it
	textBox.Text = ""
end)

textBox.FocusLost:Connect(function()
	handleInput()
end)

UI_FX local script located throughout the GUI's
local Replicated_Storage = game:GetService("ReplicatedStorage")
local UIFX = require(Replicated_Storage.UIFX)

local Hover = UIFX.HoverBigger(
	nil, 
	script.Parent, 
	UDim2.new(0.01, 0, 0.01, 0), 
	false,
	true,
	{-5, 5},
	.125,
	Enum.EasingStyle.Sine,
	Enum.EasingDirection.InOut,
	{false}
)

local Press = UIFX.ButtonPress(
	nil,
	script.Parent,
	UDim2.new(0.02, 0, 0.02, 0),
	true,
	{-5, 5},
	.125,
	Enum.EasingStyle.Sine,
	Enum.EasingDirection.InOut,
	{false}
)

Local Scripts named BackgroundAnimation

Very sloppy code, I know.

while true do
	game:GetService("TweenService"):Create(script.Parent, TweenInfo.new(1, Enum.EasingStyle.Linear, Enum.EasingDirection.Out), {Position = UDim2.new(-1, 90, -1, 0)}):Play()
	wait(1)
	script.Parent.Position = UDim2.new(-1, 0, -1, 0)
end


Model Related

image


3 Likes

way too much rotation, bg moves too fast.

5 Likes

I personally really like this Gui! Keep up the great work!

2 Likes

Hey, thanks for mentioning in your post, as I’d be happy to give you feedback!

Video Showcasing UI


  • As stated, the checker pattern could be a bit slower, which would let users focus on the text better.

  • I feel the “Are you sure?” text could be smaller, aswell as the “You are about to enter the town hall” text.

  • The corners of the UI feel a little too round.

  • The rotation on buttons when hovered could be dumbed down a little.
    I feel the outline on the “Create New Character!” button could smaller, and the text seems abit hard to see, maybe a simple white could be better.

  • The outline for the “Choose a character creation method!” menu could also be smaller.

  • The “Enter a UserId here.” textbox could be less round.


Gui Structure


  • I feel the Gui Structure doesn’t matter, just do whatever you’re comfortable with, and whats easier to script.
  • Looking at the “UI_FX” scripts you have lying throughout the UI, you should make a central LocalScript which has the UIFX module as its child (you can keep the module in ReplicatedStorage, i just stated that incase you dont need the module elsewhere.) The script has a variable which is a table, containing the UIs you’d want to use the UIFX module, it then loops through said UIs and requires the module for them.
Example (Should Work)
-- I've tried to name the variable similar to how you would so you dont need to modify them.

-- Services
local Replicated_Storage = game:GetService("ReplicatedStorage")
-- Modules
local UIFX = require(script.UIFX)
-- UI
local Guis_Folder = Replicated_Storage["Guis_Folder"]
local Confirmation_GUI = Guis_Folder["Confirmation_GUI"]
local Background = Confirmation_GUI.Background
local TownHall_GUI = Guis_Folder.TownHallGUI
local TownHall_Background = TownHall_GUI.Background
local Menu = TownHall_Background.Menu
local Buttons = Menu.Buttons
local Features = Menu.Features
local CreateNewCharacter = Features.CreateNewCharacter
-- table containing the necessary UIs.
local UIs = {
    Background.No;
    Background.Yes;
    Buttons.CreateNewCharacter;
    CreateNewCharacter;
    CreateNewCharacter.EnterUserId;
    CreateNewCharacter.UseCurrentOutfit;
}

for _, i in pairs(UIs) do

local Hover = UIFX.HoverBigger(
	nil, 
	i, 
	UDim2.new(0.01, 0, 0.01, 0), 
	false,
	true,
	{-5, 5},
	.125,
	Enum.EasingStyle.Sine,
	Enum.EasingDirection.InOut,
	{false}
)

local Press = UIFX.ButtonPress(
	nil,
	i,
	UDim2.new(0.02, 0, 0.02, 0),
	true,
	{-5, 5},
	.125,
	Enum.EasingStyle.Sine,
	Enum.EasingDirection.InOut,
	{false}
)

end

And just as a bonus, here’s how I think the “BackgroundAnimation” scripts could be cleaned up, since there seems to be a few of them, they can stay as multiple scripts for simplicity, but the rule (having a table with the needed UIs.) from the script above can apply here.

Script
while task.wait() do
    local tween = game:GetService("TweenService"):Create(script.Parent, Tween.Info(2, Enum.EasingStyle.Linear, Enum.EasingDirection.Out), {Position = UDim2.new(-1. 90, -1, 0)})
    tween:Play()
    tween.Completed:Wait()
    script.Parent.Position = UDim2.new(-1, 0, -1, 0)
end

thats all the feedback i wanted to give you, if you’d like, i can design a version of the town hall UI more that contains the tweaks i mentioned for you, but just let me know, i wish you Good Luck on your project! - KingBlueDash

3 Likes

Thanks a bunch for taking the time to give a detailed review!! Without your help, this gui would be way less animated ahahah! Although you don’t have to redesign what I’ve made in order to show me the tweaks, obviously it is your own choice to do whatever so I’d understand since all of the code is complete.

Thanks again!!

3 Likes

This GUI and script look good! Awesome job on it! How long did it take to create this system? What will this be used for?

2 Likes

Your welcome, and i don’t mind redesigning the UI, as i haven’t designed some UI in a bit, and would like to help a fellow developer.

Though i just wanna say, you don’t have to use the redesign, I’m just making it as a fun little project :slight_smile:

(side-note: incase you were wondering, UIFX will be updated probably before the end of march, as there some cool ideas i have planned.)

3 Likes

Oh alrighty then!! Cant wait to see what you produce >:)

2 Likes

Thank you so much! It took me a span of 3 days as I’m quite lazy, and I was planning on using this for a Tomodachi Life styled game for Roblox! Although I still have a ton more to learn about modern scripting techniques and how to effectively make a sound and secure game.

1 Like