Tools

Tools are a special type of Instance used to implement weapons, tools, and other interactive objects in ROBLOX.

Creating a new Tool[edit]

A Tool is a container Instance, much like a Model. To create a new Tool, right click in the Workspace, select Insert Object, and then Tool.

Tool Image01.png

Again, a Tool is just a container so it won’t show up in the 3D view if it is empty. Right click on the Tool and insert a new Part. The tool will now show up in the 3D view. In order to pick up a Tool, it needs to have a Part inside it called Handle. Rename the Part in the Tool to Handle. Now if you run the game your character will be able to pick up the Tool.

Tool Image09.png

Custom Tool Geometry[edit]

A Tool can have as many parts in it as you like. Keep in mind that only one part should be called Handle, as this part is where the tool will attach to your character’s hand. A couple of tips when building tools:

  • Make sure all of the parts are not anchored when you are finished building. If any part of the Tool is anchored, the Tool won’t be able to move and the character will get stuck when picking it up.
  • Only name one part Handle. If you have multiple parts called Handle, the tool will pick only one for the point where the character holds the tool.
  • It is critical not to use Surface welds when building a tool. Tools built with surface welds will fall apart when equipped. A Surface weld is created when you bring two parts together that have compatible surfaces (such as Smooth/Weld, Inlet/Stud). Instead, change the join behavior to Always and make sure the surfaces of all of your parts is Smooth or SmoothNoOutlines.

Tool Image07.pngTool Image06.png

Example of a tool built from multiple parts:

Tool Image02.png

In the above example the white part is the Handle. The other parts are connected together using welds.

Tools without Handles[edit]

It is possible to make a tool without a handle or any geometry. In this case the tool simply becomes an interface to player input without any visual representation in the 3D view. To make a tool like this, simply turn off the RequiresHandle property of the Tool.

Tool Image05.png

Equiping Tools[edit]

Tools can be equipped in a variety of ways. The most simple way is to have the tool in the Workspace and having a player collide with it. When this happens, the tool automatically get added to the Player’s backpack. The tool will automatically equip itself if the player does not have anything currently equipped. Note that this will only work if the RequiresHandle property of the Tool is set to true.

Tool Image04.png

You can also use the StarterPack to give tools to players. Whenever a player spawns, all of the contents of StarterPack gets copied into the player’s backpack. If you want to make sure players all start with certain equipment, the StarterPack is the best place to do this.

You can also use a Script to give a tool to a certain player. The script can put the tool (or a copy of the tool) into the player’s backpack.

local copy = game.Workspace.Tool:Clone()
copy.Parent = game.Players.Player1.Backpack

You can also force the player to equip a tool by parenting the tool into the player’s character.

local copy = game.Workspace.Tool:Clone()
copy.Parent = game.Players.Player1.Character
Be careful when inserting a tool into the character using a script! If a player already has a tool equipped and you force them to equip another, they will have both equipped which could lead to unexpected behavior.

Dropping Tools[edit]

By default, a player can drop a tool by pressing the ← Backspace key (Delete on OSX). You can prevent this behavior by setting CanBeDropped of the Tool to false.

Tools Image00.png

Action Bar Appearance[edit]

When a tool is in a player’s backpack, it will show up on the bottom of their screen in an action bar. You can customize both the tooltip and icon for a Tool in this bar. The tooltip can be set by editing the Tooltip property of the Tool.

Tool Image08.png

The icon of the Tool can be set with the TextureId property. You can set the image for this property the same way you can for a Decal as seen in Making a Painting.

Tool Scripting Basics[edit]

The purpose of tools is to provide an interface to player input, so there are many functions and events associated with them. Tools are also unique in that they can run both regular Scripts and Local Scripts. Because of their complicated relationship with scripts, it is important to understand the fundamentals of how to script with Tools.

Script vs LocalScript[edit]

Both Scripts and LocalScripts can listen to the same events and call the same functions on a Tool, so when is it important to use one over the other? Here are some general guidelines:

You should use a Script if the code:

  • Causes a change to the game world (e.g. changing player health, creating parts, etc)

You should use a LocalScript if the code:

  • Relies on player input (such as the mouse or touch input)
  • Needs to display something only to the player holding the tool

Events[edit]

There are four Tool specific events that scripts can listen to:

  • Activated: when the player starts activating the tool (when they click, tap, or press A on gamepad).
  • Deactivated: when the player releases the activation input.
  • Equipped: when the player selects the tool from their backpack.
  • Unequipped: when the player drops the tool or switches tools.

Remember, both Scripts and LocalScripts can listen to these events. Here is code for either script to hook into these events:

-- This code assumes the script is directly inside the tool. If the script is elsewhere, you will have to change the path the next variable is pointing to.
local tool = script.Parent
 
local function onEquip()
 
end
 
local function onUnequip()
 
end
 
local function onActivate()
 
end
 
local function onDeactivate()
 
end
 
tool.Equipped:connect(onEquip)
tool.Unequipped:connect(onUnequip)
tool.Activated:connect(onActivate)
tool.Deactivated:connect(onDeactivate)

Magic Wand Example[edit]

In this example we will walk through making a simple tool that creates parts when the tool’s holder clicks their mouse. We will use both a Script and LocalScript to illustrate the duties each one should perform.

We’ll start with a simple tool as seen in #Custom Tool Geometry, but any tool with a part called Handle will suffice. Insert a Script, LocalScript, and RemoteEvent into the tool. Rename the RemoteEvent to ClickEvent. The purpose of each of these elements will be made clear in the following steps.

Tool Image03.png

Getting Mouse Input[edit]

The Activated event will fire whenever the user clicks their mouse, but it does not contain information about the mouse’s information. We want our tool to create a part where the user clicks, so it is important for us to know where that click occurred. To get the mouse position, we will need to use our LocalScript, as the regular Script will be running on the Server, which doesn’t know anything about the user’s mouse.

-- Local Script
local tool = script.Parent
local player = game.Players.LocalPlayer
local mouse = player:GetMouse()
 
local function onActivate()
	local clickLocation = mouse.Hit
end
 
tool.Activated:connect(onActivate)

We start off the script by making variables for the tool, player, and the player’s mouse. Then, in the onActivate function, we store the location of the click in a variable.

Creating a Part[edit]

Now that we know where the player clicked, we need to create a part. Which script should handle this? It’s tempting to create the part right after we get the location in the LocalScript. The problem with this however is that the LocalScript is running only on tool’s player’s machine. If you have FilteringEnabled on (which is highly recommended for security purposes!), then any part created by that LocalScript won’t be copied to the server, thus making it so no one else would see the part! We want all the other players to be able to see and interact with these new parts, so we have to create the part on the Server using our Script.

-- Server Script
local function createPart(location)
	local part = Instance.new('Part')
	part.CFrame = location
	part.Parent = workspace
end

Communicating between Script and LocalScript[edit]

We now have the ability to get the mouse click location, and the ability to create a new part at an arbitrary location. But these are in different scripts! We need to get our Script and LocalScript communicating so they can work together. To do this, we will use the RemoteEvent we created earlier.

RemoteEvents are special objects we can use to send information between Scripts and LocalScripts. Each script has an event listener they can subscribe to in order to call a function when the event is fired. There are also functions used to fire the event.

Let’s start with the listener on the server Script.

-- Server Script
local tool = script.Parentlocal clickEvent = tool.ClickEventlocal clickEventConnection 
local function createPart(location)
	local part = Instance.new('Part')
	part.CFrame = location
	part.Parent = workspace
end
 
local function onClick(player, clickLocation)	createPart(clickLocation)end local function onEquip()	clickEventConnection = clickEvent.OnServerEvent:connect(onClick)end local function onUnequip()	clickEventConnection:disconnect()end tool.Equipped:connect(onEquip)tool.Unequipped:connect(onUnequip)

There are quite a few things we’ve added, so let’s go through them one at a time. First of all, we declare variables for the Tool and the RemoteEvent. We also create the variable clickEventConnection which we will use to store the event connection.

We then declare the function onClick which will be called when the listener hears the event fire. This function has two arguments, the player who fired the event and the location the player clicked (which we will pass in from the LocalScript later).

In the onEquip function, we connect the onClick function to the RemoteEvent’s OnServerEvent event. This way, whenever the RemoteEvent fires, it will call onClick. Lastly, we call disconnect on the clickEventConnection in the onUnequip function so the event won’t fire when the player doesn’t have the tool out.

You may have noticed that we pass in the player into the onClick function but we never actually use the variable. When you bind a function to OnServerEvent, the player argument is always passed in first, so we need to make sure we have a variable ready for it.

Now that we have the Script setup, we just need to modify the LocalScript a bit to get it to fire the RemoteEvent.

-- Local Script
local tool = script.Parent
local player = game.Players.LocalPlayer
local mouse = player:GetMouse()
local clickEvent = tool.ClickEvent
 
local function onActivate()
	local clickLocation = mouse.Hit
	clickEvent:FireServer(clickLocation)end
 
tool.Activated:connect(onActivate)

To get the LocalScript to fire the RemoteEvent, we call FireServer. This function can take any number of arguments we want. In this case, we just want to pass the location where the player clicked.

Now when we equip our tool, we can click to create parts!

Tool Image10.png