How to create a character Customization Menu (Part 1)

So wanna create something that we see normally in anime games? ex
(shinobi life2)
LETS GO

What we will make today!

https://gyazo.com/ab5f6f399c165738540293882875d09e?token=2b27d817d69f51b5c7ff5eb02dbddf66

Part 1 (GUI)

note : name the frame “Frame1” and the insert the textbutton you made inside frame1 and name it SkinButton1
i went with this gui but you can make yourGUI
so after youve made that gui add a textbutton and remove its text inside now choose background color of what color you want

Code 1

inside the textbutton add a local script and write this code

local replicatedStorage = game:GetService("ReplicatedStorage")

script.Parent.MouseButton1Click:Connect(function()
	replicatedStorage.Events.ColorEvent1:FireServer()
end) 

the code wont work cuz we havent put main thing go to replicated storage and make a folder called “Events” and insert a Remote Event name it “ColorEvent1”

Code 2

So now we have that cleared you can see it we cant see the colour change LETS FIX THAT!
add a script in serverscriptservice and write the following

game.ReplicatedStorage.Events.ColorEvent1.OnServerEvent:Connect(function(plr)
	local Button = game.StarterGui.Menu.Frame1.SkinColor
	local char = plr.Character
local q = BrickColor.new("Pastel brown")

for i,v in pairs(char:GetChildren())do
if v:IsA("Part")then
v.BrickColor = q
end
end

note : change pastel brown to whatever colour you want

For Adding more colours

do the same process insert a textbutton change its colour and then insert a local script and copy the code BUT instead of writing “ColorEvent1” change it to “ColorEvent2” and insert a remote event in the events folder we made named the same and then go to serverscriptservice script and paste the script again instead of TextButton1 write TextButton2 and then change the “Colorevent1” to ColorEvent2"

like this

game.ReplicatedStorage.Events.ColorEvent1.OnServerEvent:Connect(function(plr)
	local Button = game.StarterGui.Menu.Frame1.SkinColor
	local char = plr.Character
local q = BrickColor.new("Brown")

for i,v in pairs(char:GetChildren())do
if v:IsA("Part")then
v.BrickColor = q
end
end

local script one



local replicatedStorage = game:GetService("ReplicatedStorage")

script.Parent.MouseButton1Click:Connect(function()
	replicatedStorage.Events.ColorEvent2:FireServer()
end)

thats what we have for today next part we be released soon

next part will have HAIR and clothing

Finished

https://gyazo.com/ef726288069147d1bb1b4e8c78b69096
note :you may not see the difference but it does work

24 Likes

The fact that you have remote events for every color is super inefficient. It can be solved by sending the data of what color the player chose and sending that info to one remote event.

6 Likes

nice idea but i believe it might be hard for beginners

2 Likes

Then you shouldn’t teach inefficient practices to beginners, right?


What if the player character is R6? This is not how you should do it. Instead of writing a long chunk of code like this;

A better way to do this is
local char = plr.Character

for i, part in pairs(char:GetChildren()) do -- Loop through every child of character
   if part:IsA("BasePart") then -- check if its a basepart (meshpart, union, normal part etc ) 
      part.BrickColor = q -- change color
   end
end
7 Likes

oh thanks for improving the code i am doing from what ive learnt so far

1 Like

i am pretty new so i am doing this till what ive learnt so far

2 Likes

ive changed the code now it looks different

2 Likes

There are some things I’d like to mention out. If you won’t do anything with index, you can replace i with a _,. Since you are looping through an array since character:GetChildren() returns a table of everything which is inside the character, it’s much wiser to use ipairs.

Also it would be wise to check the data type of q since the script would error it wasn’t a BrickColor data type. You should also change q to something more readable which makes sense.

Here’s how a remastered version of your code would look like:

local character = plr.Character

for _, part in ipairs(char:GetChildren()) do -- Loop through every child of character
   if part:IsA("BasePart") and typeof(color) == "brickcolor" and part.BrickColor ~= color then -- check if its a basepart (meshpart, union, normal part etc ) 
       part.BrickColor = color -- change brick color
   end
end

Though checking if a brickcolor isn’t the same isn’t necessary but I’d like to have it since it’s my practice to not change something to x if it’s already x.

7 Likes

I was going to make that for a game, this is definitly going to help. Thanks! :slightly_smiling_face:

nope next part will come soon tho : )

Hmm, don’t know why you’re waiting for the character to load, since the script is firing from a remote, it’d better to check if the character even exists or not.

This is optional.

Can you explain more about this? If you’re talking about the speed, its almost negligible. The array returned by GetChildren() has all numerical indexes so it doesn’t make a difference to use ipairs or pairs.

I didn’t see if it was fired from a remote. It is always good practice to use ipairs over pairs when looping through an array. Ipairs will loop definitely while pairs will loop indefinitely.

" you can replace i with a _,"

Why put it if you don’t want to use it? That’s a bad practice. Same goes for not using self in a function that uses :.

2 Likes

In my game i`m using gui ( start customization and leveling changes) for changing Humanoid Description System - its works pretty good with colors.
Waiting for hair\accessories part - for now its works very unstable with my solution - sometimes i cant see actual changes on another player.

1 Like

I’ll be waiting for it :slightly_smiling_face:

1 Like

its coming tommrrow because i havent scripted the hair or any other parts yet lol

2 Likes

ill give a link to part 2 tommrrow

2 Likes

ok folks the part 2 is coming tommorrow

1 Like

There are much more effecient ways to do this. For example:

Local Script (Put in the same frame as all the color buttons)

local ColorChange = game.ReplicatedStorage:WaitForChild('ColorChange')
local buttonTable = script.Parent:GetChildren()

for index, button in pairs(buttonTable) do
    if button:IsA('Button') then
        button.MouseButton1Click:Connect(function()
            ColorChange:FireServer(button.BackgroundColor3)
        end
    end
end

Server Script

local ColorChange = game.ReplicatedStorage:WaitForChild('ColorChange')

ColorChange.OnServerEvent:Connect(player, color)
if player.Character then
    local character = player.Character

    for index, entity in pairs(character:GetChildren()) do
        if entity:IsA('BasePart') then
            entity.Color3 = color
        end
    end
end

I’m not 100% if entity.Color3 = color is correct, I wrote it off of memory and in like half a minute. That’s just an example how you can make it MUCH more effecient. Please dont show beginners ineffecient scripting practices. Its great how you are trying to contribute to the continue, but maybe you should begin by learning a little bit more and then trying to teach others about what you learnt. Have a great day! :slight_smile:

4 Likes

I do not even believe this is needed. You can take part of the event handler script and make it work solely from the button. Like this:

script.Parent.MouseButton1Click:Connect(function()
local plr = game.Players.LocalPlayer
local q = BrickColor.new("Pastel brown")

for i,v in pairs(char:GetChildren())do
    if v:IsA("Part")then
    v.BrickColor = q
   end
end
end)

I’m sorry about the indentation, I’m on mobile at the moment. This is more efficient, but it is more client-sided. If you would like to make it more protected against exploiters, you can do it the other way.

part 2 has been delayed @everyone