Create your first plugin! - Guide on how to use widgets and other stuff

About this tutorial

This is my second community tutorial! This time I will be going to teach you how to create your first plugin with studio widgets. I have tried to make it beginner friendly with in-depth code explanation but, you will need to have basic RobloxLua knowledge.

I want to start with a simple yet perfect example for this tutorial.

This plugin name is “EzKillBricks”. You’ll learn how create a plugin which converts all the parts you have selected to kill bricks.

Lets get going!

Step 1:

image1

Insert a folder in ServerScriptService, name it whatever you want -> Insert A script and name it whatever you want.

Step 2:

Here begins the coding part, open the script and begin writing your poetic code!

--// SetUp Plugin \\--

local bar = plugin:CreateToolbar("Tutorial"); -- Create and set toolBar name

local button1 = bar:CreateButton( -- Create a button
 "Convert To Kill Brick", -- Title
 "Convert baseparts to kill bricks", -- Description
 "http://www.roblox.com/asset/?id=5036907375" -- Icon asset id
);

This is the basic setup of the plugin. I have explained it with comments

Step 3:

Now lets add the widgets!

local info = DockWidgetPluginGuiInfo.new( -- Create your widget info
	Enum.InitialDockState.Float,  -- Dock State
	false,   -- toggle enabled 
	true,    -- sets wheater it overrides the previous window or not 
	200,     -- width 
	44, 	 -- height    
	200,     -- min width
	44       -- min height
)
 
local widget1 = plugin:CreateDockWidgetPluginGui("EzKillBrick Window", info) -- create your widget.

In the first info array we define our widget attributes
then create the widget with plugin:CreateDockWidgetPluginGui(string, your DockWidgetInfo)

So now if you will run it you wont see the widget because I have disabled it by setting it to false.

Step 4:

Lets head on to the main part! Now lets add a TextButton to the widget1


--// Main \\--

local textB1 = Instance.new("TextButton");
textB1.Text = "Click To Convert!";
textB1.Size = UDim2.new(1, 0, 1, 0);
textB1.Visible = true;
textB1.Parent =	widget1;

local UiListLayout = Instance.new("UIListLayout");
UiListLayout.Parent = widget1;

Create your textButton.
You can customize however you want.
set the text button parent to widget1; textB1.Parent = widget1;


Create a UiListLayout. UiListLayouts are used to automatically maintain the position of all the UI’s in a List Layout under its parent.
In this case we’re parenting the UiListLayout to the widget1, widget1 consists of TextButton. So now the TextButton will maintain its position corresponding to other UI’s in a list layout.

It will help when you have many TextLabels.

Step 5:

Lets add the function which will enable our Widget1 when toolbar is clicked!


function PluginCode()
	widget1.Enabled = true;
end;


--// Connect \\--
button1.Click:Connect(PluginCode);

Use the .Click event whenever the button is clicked to trigger the PluginCode() function

In PluginCode() function, when triggered it will set the widget1 Enabled to true.

Step 6:

Now lets do the main fucntion

local selection = game:GetService("Selection")

function MainFunc()
	local selected = selection:Get();
	for i, v in ipairs(selected) do
		if v:IsA("BasePart") then
			v.BrickColor = BrickColor.new("Really red");
			v.Material = Enum.Material.Granite;
		else
			warn("Select a basepart!")
		end;
	end;
end;

textB1.MouseButton1Click:Connect(MainFunc);

Explanation

local selection = game:GetService("Selection") - This line gets the “Selection” class.

Selection class is used when you want to get all the objects you are selecting in edit mode


function MainFunc()
	local selected = selection:Get();
	for i, v in ipairs(selected) do

	end;
end;

here selected is getting all the parts you have currently selected by calling selection:Get();
So now selected is a table


	for i, v in ipairs(selected) do

	end;

here we’re iterating through every object in the selected table.


	for i, v in ipairs(selected) do
		if v:IsA("BasePart") then
			v.BrickColor = BrickColor.new("Really red");
			v.Material = Enum.Material.Granite;
		else
			warn("Select a basepart!")
		end;
	end;

here the code is checking if the current value (v) you’re iterating through Is A (that means if the object belongs to BasePart Superclass) BasePart.

A basepart is like a superclass of all types of parts for example; MeshPart, NormalPart, Unions.

And if the value or object is a BasePart then;

v.BrickColor = BrickColor.new("Really red"); – set the object color to red

v.Material = Enum.Material.Granite; – change the material to granite to make it look almost like a lava brick

But if

the current value or object is not a BasePart then

then a warning will be displayed in the output telling you to select a basepart; warn("Select a basepart!")


Now lets connect the Mainfunc with textB1.MouseButton1Click:Connect(MainFunc);

SO, now if you select baseparts and click on the TextButton then the parts will change the material and color.

Step 7:

Now lets give life to the KillBricks by adding a killscript in them.

function WriteScript(part) --  part is the object you send
	local newScript = Instance.new("Script");
	newScript.Name = "KillScript";
	newScript.Source = [[
script.Parent.Touched:Connect(function(p)
	if game.Players:GetPlayerFromCharacter(p.Parent) then
		local hum = p.Parent:FindFirstChildOfClass("Humanoid");
		hum.Health = 0; 
	end;
end);
]]
	newScript.Parent = part;
	return;
end;

Explanation

function WriteScript(part) --  part is the object you send
	local newScript = Instance.new("Script");
	newScript.Name = "KillScript";
         
    --  

    newScript.Parent = part;
	return;

a new script is instanced in the variable newScript and then named “KillScript”

Here the function has part as the parameter. part is the basepart. the newScript will parent it self to the part; newScript.Parent = part;


	local newScript = Instance.new("Script");
	newScript.Name = "KillScript";
	newScript.Source = [[
script.Parent.Touched:Connect(function(p) -- Get the part which touched
	if game.Players:GetPlayerFromCharacter(p.Parent) then -- Check if the part is a player
		local hum = p.Parent:FindFirstChildOfClass("Humanoid"); -- find the humanoid
		hum.Health = 0; -- Kill the character by changing `Health` to `0`
	end;
end);
]]
	newScript.Parent = part;
	return;

Script.Source can be only be used by either plugins or the command bar.

with .Source you write lines of code inside scripts. So here we’re writing a basic KillScript inside this newly Instanced script.

Click here for more information about .Source

Step 8:

Now you need to call this function from another script; add this line
WriteScript(v);

in the MainFunc()

	for i, v in ipairs(selected) do
		if v:IsA("BasePart") then
			v.BrickColor = BrickColor.new("Really red");
			v.Material = Enum.Material.Granite;
			WriteScript(v);
		else
			warn("Select a basepart!")
		end;
	end;

Step 9:

Lets now save the plugin to actually run it!

Select the folder
image2

A click on Save as Local Plugin...

Save it in the Roblox Plugin Directory.
image4

Step 10:

You’re done! :partying_face: ! Congrats you created your own plugin!


Full Code (Dont just copy the code but try to learn what it means)

–// SetUp Plugin \–

local bar = plugin:CreateToolbar("Tutorial by FastAsFlashDev_Dev"); -- Create and set toolBar name

local button1 = bar:CreateButton(
 "Convert To Kill Brick", -- Title
 "Create an empty script", -- Description
 "http://www.roblox.com/asset/?id=5036907375" -- Icon
);


local info = DockWidgetPluginGuiInfo.new(
	Enum.InitialDockState.Float,  -- Dock State
	false,   -- toggle enabled 
	true,    -- sets wheater it overrides the previous window or not 
	200,     -- width 
	44, 	 -- height    
	200,     -- min width
	44       -- min height
)
 
local widget1 = plugin:CreateDockWidgetPluginGui("EzKillBrick Window", info)


--// Main \\--

local selection = game:GetService("Selection");

local textB1 = Instance.new("TextButton");
textB1.Text = "Click To Convert!";
textB1.Size = UDim2.new(1, 0, 1, 0);
textB1.Visible = true;
textB1.Parent =	widget1;

local UiListLayout = Instance.new("UIListLayout");
UiListLayout.Parent = widget1;

function MainFunc()
	local selected = selection:Get();
	for i, v in ipairs(selected) do
		if v:IsA("BasePart") then
			v.BrickColor = BrickColor.new("Really red");
			v.Material = Enum.Material.Granite;
			WriteScript(v);
		else
			warn("Select a basepart!")
		end;
	end;
end;

function WriteScript(part)
	local newScript = Instance.new("Script");
	newScript.Name = "KillScript";
	newScript.Source = [[
script.Parent.Touched:Connect(function(p)
	if game.Players:GetPlayerFromCharacter(p.Parent) then
		local hum = p.Parent:FindFirstChildOfClass("Humanoid");
		hum.Health = 0; 
	end;
end);
]]
	newScript.Parent = part;
	return;
end;

function PluginCode()
	widget1.Enabled = true;
end;


--// Connect \\--
button1.Click:Connect(PluginCode);
textB1.MouseButton1Click:Connect(MainFunc);


Install the Plugin here

My other Tutorial(s)

Full Guide on how to use PBR Materials in Blender

Screenshots

image5
imsgr6
image7


I will be glad to hear any feedback! If you want to ask question you can either ask me DMs or in the reply section.

Thank you for reading!

40 Likes

It might be a bad idea to recommend using CollectionService for kill parts instead of inserting the same script into every single part. It makes updating the kill part script harder that it would be if you would use CollectionService. Another thing to note is that one of the uses for CollectionService is this very said issue and should be considered a better practice over adding scripts into every part.

3 Likes

This is very nice of you for teaching new people on how to create plugins! Good job on that! Hope you have a wonderful day!

4 Likes

Wow! This helped me a lot!!!

2 Likes

Wow! I’ve been wanting to learn how to create plugins. Thank you for creating this!

2 Likes

For my script, there’s an error:
ServerScriptService.Plugin:3: attempt to index nil with ‘CreateToolbar’

when I have the line:

local toolbar = plugin:CreateToolbar(“Custom Grid Creation”)

Why?