Once I equip my melee that has an inspect animation keybinded to F, once I unequip it, I can still press F to “inspect” nothing, here is a video of it.
local Humanoid = Character:WaitForChild("Humanoid")
local Animator = Humanoid:FindFirstChild("Animator")
UIS.InputBegan:Connect(function(Input)
if Humanoid then
if Animator then
local AnimationTrack = Animator:LoadAnimation(InspectAnimation)
if Input.KeyCode == Enum.KeyCode.F then
AnimationTrack:Play()
end
end
end
end)
This is because you’ve not managed the RBXScriptConnection disposable you’ve created by calling ::Connect on UserInputService.InputBegan<RBXScriptSignal> . You need to disconnect these listener(s) when you’re finished with them.
-- Note: make sure to create a new handler every time someone equips the tool ...
local beganHandler = UserInputService.InputBegan:Connect(function (input, gameProcessed)
-- your handler here
end)
tool.Unequipped:Connect(function ()
-- disconnect the handler so we're no longer listening
-- to the input event(s)
if beganHandler and beganHandler.Connected then
beganHandler:Disconnect()
end
end)
That probably is the easiest way unless you want to check if the tool is equipped every time someone presses the ‘F’ key, but even then, managing and disposing connections etc is good practice to avoid memory leaks - see here.
Which part did you not understand so I can try to clarify?
I see, it’s a little tough to help without knowing exactly what you don’t understand.
See the following example but please do see the comments attached - they should be helpful in explaining what’s actually going on line by line.
Example Tool
--[!] SERVICES
-- i.e. any services we need
local PlayerService = game:GetService('Players')
local UserInputService = game:GetService('UserInputService')
local ReplicatedStorage = game:GetService('ReplicatedStorage')
--[!] UTILS
-- i.e. any utility functions
--[=[
used to check whether a character is alive
i.e. one that...
1) has a humanoid with health greater than 0
and has a state other than Enum.HumanoidStateType.Dead
2) has a valid root part
@param character Instance - the character model we want to check
@returns boolean - reflects the alive status of a character instance
]=]
local function isAlive(character)
if typeof(character) ~= 'Instance' or not character:IsA('Model') or not character:IsDescendantOf(workspace) then
return false
end
local humanoid = character:FindFirstChildOfClass('Humanoid')
local humanoidState = humanoid and humanoid:GetState() or Enum.HumanoidStateType.Dead
local humanoidRootPart = humanoid and humanoid.RootPart or nil
if humanoidState == Enum.HumanoidStateType.Dead or not humanoidRootPart then
return false
end
return true
end
--[!] MAIN
-- i.e. the main script
local tool = script.Parent -- the tool this LocalScript relates to
local player = PlayerService.LocalPlayer -- our local player
local disposables = { } -- a list of disposable(s), see below for more information
local function toolEquipped()
local handle = tool:FindFirstChild('Handle') -- the tool's handle
local inspectAnimation = ReplicatedStorage:FindFirstChild('SomeInspectAnimation') -- i.e. your animation asset
-- now that the player has equipped the tool
-- we need to set up the listener(s) that we
-- need to perform the action(s) that are required
--
local inputBegan = UserInputService.InputBegan:Connect(function (input, gameProcessed)
-- first, let's make sure we ignore all input events that are related to other
-- things e.g. when a user is typing on a keyboard in the /chat
--
if gameProcessed then
return
end
-- now we need to confirm that the player is:
-- 1) is alive
-- 2) has a valid humanoid & an animator
local character = player.Character
local humanoid = isAlive(character) and character:FindFirstChildOfClass('Humanoid') or nil
local animator = humanoid and humanoid:FindFirstChildOfClass('Animator') or nil
if not animator then
return
end
-- now let's check to see whether the user tried to do the inspect animation
local keyCode = input.KeyCode
if keyCode == Enum.KeyCode.F then
-- if the animation doesn't exist then let's ignore it
if not inspectAnimation then
return
end
-- check to see if we already have an inspect track
-- that we've loaded already
local track = disposables._inspectTrack
if not track then
-- since we don't have the inspect animation track loaded & cached
-- let's load that track now into the animator
track = animator:LoadAnimation(inspectAnimation)
disposables._inspectTrack = track
end
-- if the track is already playing then let's ignore this event
if track.IsPlaying then
return
end
-- play the track, taking 0.1s to fade in
track:Play(0.1)
end
end)
-- insert the `RBXScriptConnection` from UserInputService.InputBegan
-- into our `disposables` list so that we can clean it up when the person
-- unequips the tool
--
-- doing this means that we'll no longer be listening to the player
-- pressing the "F" key so we'll stop trying to do the animation
-- once the tool is unequipped
--
table.insert(disposables, inputBegan)
-- e.g. do something else once the tool is unequipped...
--
-- note: see the unequip handler comments
-- for why I added this particular example
--
if handle and handle:IsA('BasePart') then
handle.Color = Color3.new(0, 1, 0)
end
end
local function toolUnequipped()
-- e.g. do something else when we unequip...
--
-- note: I added this so you could press `Backspace`
-- to drop the tool in the world to visually
-- show that the unequip handler was being
-- called etc
--
local handle = tool and tool:FindFirstChild('Handle')
if handle and handle:IsA('BasePart') then
handle.Color = Color3.new(1, 0, 0)
end
-- now let's clean up all of our disposables
-- i.e. things that we needed when the tool was equipped
-- but can be disposed now that we're no longer equipping
-- the tool
--
-- e.g. the Input listener(s) and any playing animation(s)
-- that we added to the `disposables` list when the tool
-- was equipped and the `toolEquipped()` function was called
--
-- first let's create a new disposables
-- table while we clean up the old disposables
local elements = disposables
disposables = { }
-- now we need to loop through all the element(s)
-- in the disposables list and dispose of them
--
local k, v = next(elements)
while k do
local t = typeof(v)
-- we need to dispose of these elements in different ways
-- depending on their type
if t == 'RBXScriptConnection' and v.Connected then
-- we're a connection, e.g. UIS.InputBegan, so we need to disconnect
-- the listener
v:Disconnect()
elseif t == 'Instance' then
-- we're an instance so we need to call `:Destroy()` on the instance
-- pcall is being used here to safely do this in case the instance is
-- already destroyed
--
-- you can read about pcall here: https://create.roblox.com/docs/reference/engine/globals/LuaGlobals#pcall
--
if v:IsA('AnimationTrack') then
-- ::Stop() before ::Destroy() because, atm,
-- when you destroy an anim without stopping it
-- the humanoid doesn't resolve the anim weights
pcall(function ()
v:Stop()
v:Destroy()
end)
else
-- we're something other than an `AnimationTrack`
-- so we just need to destroy the instance instead
--
-- e.g. in the case you added a part to the disposable list
--
pcall(v.Destroy, v)
end
elseif t == 'function' then
-- we're a function, so let's call that function safely
-- to perform any arbitrary cleanup method we've added
pcall(v)
end
-- get the next element in the disposables list
k, v = next(elements, k)
end
end
-- Now we need to listen to when our tool is equipped/unequipped
--
-- AFAIK the `RBXScriptSignals` from Tool.Equipped & Tool.Unequipped
-- don't need to be disposed of because `::Destroy()` is called on
-- the tool when you die and a new tool is inserted into the
-- player's `Backpack` from the `StarterPack`
--
tool.Equipped:Connect(toolEquipped)
tool.Unequipped:Connect(toolUnequipped)
Let me know if you have questions.
P.S. I should note that people usually use a library to handle this for them instead of using a disposable list as in the example above.
Popular examples that would be good for you to look at may include: Maid, Janitor, Trove. There’s also an article written by Quenty explaining Maid class usage here that may be helpful to you.