Equip/unequip Tool Animation Script

I would like to get a feedback & help how can I improve the code.

It works all and from one side Im really glad that it works as expected but from the other side there is a issue that I don’t know how to fix.

I want that this code would work as it works right now but without the glitches, when the user spams the tool (equip/unequip) it glitches out, phone might be still there, animation doesnt play anymore and probably alot of motor6d/clones are created…

What I want:
When user spams the Tool nothing should glitch out →
It will just reverse animation (when unequipped) then play animation normaly again (when equipped again mid-unequip), freeze at last frame (if it wasnt unequipped again) so the player stays in the “looking at phone” position.

I don’t want to do a hard-debounce if that’s possible

-- Ignore the Prints, Its just for me as logs.


-- some variables declarations
local tool = script.Parent
local fakeTool = game.ReplicatedStorage:WaitForChild("PhoneModel")


local lplayer = game:GetService("Players").LocalPlayer
local character = lplayer.Character or lplayer.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")

local animator = humanoid:FindFirstChild("Animator")


print(animator.Parent.Name .. " [ANIMATOR PARENT]")

local phoneAnim = animator:LoadAnimation(script.Animation)

-- just a function to make the moon animator animation work properly for the phone (so it rotates properly etc.)
local function createMotor(bodypart, part1, what)
	bodypart = character:WaitForChild(bodypart)
	
	
	local motor6d = Instance.new("Motor6D", bodypart)
	motor6d.Name = what
	motor6d.Part0 = bodypart
	motor6d.Part1 = part1
	motor6d.C0 = CFrame.new(-0.118, -0.97, 0.03) * CFrame.Angles(0, math.rad(-90), math.rad(-180))
	return motor6d
end



local cln
local motor

-- clone the phonemodel into players character and then add a Motor6D
-- Freeze at last Frame so it looks like the player still looking at his phone
tool.Equipped:Connect(function()
	print("[Equipped TEST]")
	
	cln = fakeTool:Clone()
	cln.Parent = character
	
	motor = createMotor("Right Arm", cln.Handle, "Phone Motor")
	
	
	phoneAnim:Play()
	
	task.wait(phoneAnim.Length * 0.95)
	phoneAnim:AdjustSpeed(0)
	
end)

-- reverse the animation, so it looks like the player just puts away his phone
tool.Unequipped:Connect(function()
	print("[Unequipped TEST]")
	
	phoneAnim:AdjustSpeed(-1)
	
	task.wait(phoneAnim.Length)
	
	cln:Destroy()
	motor:Destroy()
end)

its my first time trying to make a equip/unequip script that will work with the moon animator 2 animation (I spent 2-3 days figuring out how to atleast do this right now, because in YT i couldnt find a proper tutorial with scripting. The Animation was easily made, under 5minutes tho)

Thus I would like to get feedback & advice/solutions :grinning_face:

Here’s the LocalScript that I use for changing the default tool animation. You can replace carryAnim for your animation.

LocalScript
local tool = script.Parent
local player = nil
local char = nil
local carryAnim = tool:WaitForChild("CarryAnim")
local carryTrack = nil

local function doAnimations(char, equipped)
	local hum = char:WaitForChild("Humanoid")
	local animator = hum:WaitForChild("Animator")
	if equipped then
		carryTrack = animator:LoadAnimation(carryAnim)
		carryTrack:Play()
	elseif carryTrack then
		carryTrack:Stop()
		carryTrack:Destroy()
	end
end

local function onEquipped()
	player = game.Players.LocalPlayer
	char = player.Character or player.CharacterAdded:Wait()
	doAnimations(char, true)
end

local function onUnequipped()
	player = nil
	doAnimations(char, false)
end

tool.Equipped:Connect(onEquipped)
tool.Unequipped:Connect(onUnequipped)

By the way, you should not clone the phone (It’s a LocalScript, so other players can’t see the phone model). Instead, parent the Handle of the PhoneModel into the Tool.

I’m not sure if this is exactly what you’re looking for, but I learned how to do this
from this video:

Specifically the “Door” part of the video, where the animation can play forward and backward.


  • The start = phone not equipped
  • The end = phone fully equipped
  • A marker called "Pause" is placed at the final pose


The script that I used:

local tool = script.Parent
local character = game:GetService("Players").LocalPlayer.Character
local animation = script.Parent.Animation
local animator = character:WaitForChild("Humanoid"):WaitForChild("Animator") :: Animator

local animationTrack = animator:LoadAnimation(animation)
local speed = 2

tool.Equipped:Connect(function()
	if animationTrack.IsPlaying then
		animationTrack:AdjustSpeed(speed)	
	else
		animationTrack:Play(nil, nil, speed)
	end
end)

tool.Unequipped:Connect(function()
	if animationTrack.IsPlaying then
		animationTrack:AdjustSpeed(-speed)
	end
end)

animationTrack:GetMarkerReachedSignal("Pause"):Connect(function()
	if not tool:IsDescendantOf(character) then return end

	animationTrack:AdjustSpeed(0)
end)

Result:


This would save a lot of time and make everything simple