Trouble with animating a player equipping/unequipping a flashlight

Hey! I did not find any topic with something like this, so decided to write one.

I am trying to animate the player equipping and unequipping a flashlight.
But it is not working. What should I do to fix this issue? Here is a video with the issue and the code.


local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")

local flashlight = ServerStorage:WaitForChild("Flashlight")

local flashlightEvent = ReplicatedStorage:WaitForChild("RemoteEvents"):WaitForChild("Flashlight")

Players.PlayerAdded:Connect(function(player)
	local newFlashlight = flashlight:Clone()
	newFlashlight.Parent = player
end)

flashlightEvent.OnServerEvent:Connect(function(player, typeOfEvent)
	
	local equipFlashlight
	local idleFlashlight
	local unequipFlashlight
	local humanoid = player.Character.Humanoid
	local AnimationsFolder = ReplicatedStorage:WaitForChild("Animations")
	
	if typeOfEvent == "Equip" then
		player.Flashlight.Parent = player.Character
		
		equipFlashlight = humanoid:LoadAnimation(AnimationsFolder:WaitForChild("EquipFlashlight"))
		equipFlashlight:Play()
		equipFlashlight.Stopped:Wait()
		
		idleFlashlight = humanoid:LoadAnimation(AnimationsFolder:WaitForChild("Flashlight"))
		idleFlashlight:Play()
		
	end
	if typeOfEvent == "Unequip" then
		player.Character.Flashlight.Parent = player
		
		idleFlashlight:Stop()
		unequipFlashlight = humanoid:LoadAnimation(AnimationsFolder:WaitForChild("UnequipFlashlight"))
		unequipFlashlight:Play()
		
	end

end)


Some more details:

I am not using roblox’s default backpack system, so my flashlight is a tool located on the server storage, every time a player is added, a new clone of that flashlight is parented to the player (not character). And the flashlight is parented to character or player when the player presses F (To equip and unequip)

I am not using the default equip / unequip tool animation

This scipt is located in Server Script Service and is a Server Script.

3 Likes

I have a few questions regarding:

  • What object is the flashlight?
  • Is this a keybind flashlight?

Try to stop the equipflashlight animation when the tool is unequipped

equipFlashLight:Stop()

Im going to assume that this script is located in the flashlight itself. If that’s the case then I would suggest storing the loaded animations outside of the event, That way it doesn’t create a new animation each time the event is fired

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")

local flashlight = ServerStorage:WaitForChild("Flashlight")
local flashlightEvent = ReplicatedStorage:WaitForChild("RemoteEvents"):WaitForChild("Flashlight")

local equipFlashlight
local idleFlashlight
local unequipFlashlight

flashlightEvent.OnServerEvent:Connect(function(player, typeOfEvent)
	local Humanoid = player.Character.Humanoid
	
	if not equipFlashlight then
		equipFlashlight = Humanoid:LoadAnimation(ReplicatedStorage:WaitForChild("Animations"):WaitForChild("EquipFlashlight"))
	end
	if not idleFlashlight then
		idleFlashlight = player.Character.Humanoid:LoadAnimation(ReplicatedStorage:WaitForChild("Animations"):WaitForChild("Flashlight"))
	end
	if not unequipFlashlight then
		unequipFlashlight = player.Character.Humanoid:LoadAnimation(ReplicatedStorage:WaitForChild("Animations"):WaitForChild("UnequipFlashlight"))
	end

	if typeOfEvent == "Equip" then
		player.Flashlight.Parent = player.Character

		equipFlashlight:Play()
		equipFlashlight.Stopped:Wait()

		idleFlashlight:Play()

	elseif typeOfEvent == "Unequip" then
		player.Character.Flashlight.Parent = player

		idleFlashlight:Stop()
		unequipFlashlight:Play()
	end
end)

Okay, I added more details about the flashlight to this topic :slightly_smiling_face:

I tried this but still didn’t work

I added more details to the topic and changed the code now, but still not working

Is it still doing the same thing or something different?

I really recommend running the animations from the clients and in a different way than what you have here. on the client be sure to use and wait for the animator on the humanoid so animations will replicate to all clients

Try this using the animator and also stopping the equip animation on unequip just to make sure. other than that it maybe something to do with priority of the animations

also check your output with the prints for testing

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")

local flashlight = ServerStorage:WaitForChild("Flashlight")

local flashlightEvent = ReplicatedStorage:WaitForChild("RemoteEvents"):WaitForChild("Flashlight")

Players.PlayerAdded:Connect(function(player)
	local newFlashlight = flashlight:Clone()
	newFlashlight.Parent = player
end)

flashlightEvent.OnServerEvent:Connect(function(player, typeOfEvent)

	local equipFlashlight
	local idleFlashlight
	local unequipFlashlight
	local humanoid = player.Character.Humanoid
	local Animator = humanoid:WaitForChild('Animator')   -- also you may want to use the animator instead of the humanoid loading
	local AnimationsFolder = ReplicatedStorage:WaitForChild("Animations")

	if typeOfEvent == "Equip" then
		player.Flashlight.Parent = player.Character

		equipFlashlight = Animator:LoadAnimation(AnimationsFolder:WaitForChild("EquipFlashlight"))
		equipFlashlight:Play()
		equipFlashlight.Stopped:Wait()
		print('Aimation1Finish')
		idleFlashlight = Animator:LoadAnimation(AnimationsFolder:WaitForChild("Flashlight"))
		idleFlashlight:Play()
		print('Aimation2')
	end
	if typeOfEvent == "Unequip" then
		player.Character.Flashlight.Parent = player
		equipFlashlight:Stop()  -- Try stopping the animation here incase its somehow messing with it
		
		idleFlashlight:Stop()
		print('Stopped Animations 1 2')
		unequipFlashlight = Animator:LoadAnimation(AnimationsFolder:WaitForChild("UnequipFlashlight"))
		unequipFlashlight:Play()
		print('Animation3')
	end

end)

an easy way to write the local script with the setup you are using is to just connect to the child added and child removed on the players character if the child added is flashlight then do equip animation then idle. and if removed is flashlight then stop animation or do unequip

also you can set this up with just one animation and use animation markers with GetMarkerReachedSignal
https://create.roblox.com/docs/reference/engine/classes/AnimationTrack#GetMarkerReachedSignal

1 Like

Thank you for the details I'll give my suggestions on the matter.


Explanation


I would use a server script to handle the equip/unequip/activate system. I’d place the tool in character and destroy it for unequip/unequip. I’d then fire a remote event from the tool script once it gets activated. Animations can be done through localscripts and automatically replicated to the server; therefore, I’d write the animation script within a localscript and place it in the tool.

The problem with the animations is it’s not stopping the animation properly therefore we move it around and use variables as slots. When the tool gets destroyed it will then detect it and run the unequip script.

1. Equiping / Unequiping

Use the same system you’re currently using to equip the flashlight. It’s exactly what I would do:

• StarterGui localscript:

-- Localscript within StarterGui
local deb = false

game:GetService("UserInputService").InputBegan:Connect(function(input, isTyping)
	if isTyping then return end -- If chatting it won't run
	
	if input.KeyCode == Enum.KeyCode.F then
		if not deb then -- This technique helps if you want to press F instead of hold
			deb = true
			game.ReplicatedStorage.RemoteEvents.Flashlight:FireServer("Equip")
		else
			deb = false
			game.ReplicatedStorage.RemoteEvents.Flashlight:FireServer("Unequip")
		end
		
	end
end)

• ServerScriptService script:

-- Normal script within ServerScriptService
local RemoteEvents = {
	["Flashlight"] = game.ReplicatedStorage.RemoteEvents.Flashlight;
};

local deb = false

RemoteEvents.Flashlight.OnServerEvent:Connect(function(plr, eventType)
	local char = plr.Character or plr.CharacterAdded:Wait() -- Gets character
	
	if eventType == "Equip" then
		local Flashlight = game.ServerStorage.Flashlight:Clone() -- Adds flashlight to character
		Flashlight.Parent = char

	elseif eventType == "Unequip" then
		local Flashlight = char:FindFirstChild("Flashlight") 
		if Flashlight then 
			Flashlight:Destroy() -- Removes flashlight from character
		end

	elseif eventType == "Activate" then -- Use this for enabling flashlight globally
		if not deb then -- Enable light
			deb = true
		else -- Disable light
			deb = false
		end
		
	end
end)

2. Animations


• Tool localscript

-- local script within the tool
local equip, unequip, idle -- Animation Slots

local char = game.Players.LocalPlayer.Character or game.Players.LocalPlayer.CharacterAdded:Wait() -- Waits till character spawns

script.Parent.Equipped:Connect(function()
	if not equip then 
		equip = char.Humanoid:LoadAnimation(game.ReplicatedStorage.Animations["EquipFlashlight"]) -- Sets animation slot
	end

	equip:Play()
	equip.Stopped:Wait()

	if not idle then
		idle = char.Humanoid:LoadAnimation(game.ReplicatedStorage.Animations["IdleFlashlight"]) -- Sets animation slot
	end

	idle:Play()
end)

script.Parent.Unequipped:Connect(function()
	if not unequip then
		unequip = char.Humanoid:LoadAnimation(game.ReplicatedStorage.Animations["UnequipFlashlight"]) -- Sets animation slot
	end

	idle:Stop()
	unequip:Play()
end)

script.Parent.Destroying:Connect(function()
	if not unequip then
		unequip = char.Humanoid:LoadAnimation(game.ReplicatedStorage.Animations["UnequipFlashlight"]) -- Sets animation slot
	end

	idle:Stop()
	unequip:Play()
end)


script.Parent.Activated:Connect(function()
	game.ReplicatedStorage.RemoteEvents.Flashlight:FireServer("Activate") -- Use to activate flashlight globally
end)


Test it myself and everything works perfectly; hope this helps.

1 Like

Thanks bro, it helped me! I didn’t know that animations played on the client’s side play for all players, and I didn’t know that using the animator to load the animations was better than using humanoid, good to know! Thank you :grin:

I really liked your system of organization using tables, makes the code even more legible! I will use your debounce system, I really liked it too!

I did what you wrote and the issue was fixed! I do not know where it was, but thank you for your kindness and you time spent writing!

1 Like

I’m glad you liked the organization, appreciate it. I didn’t organize the code that much and wrote it in a high-level state so it’s easier for you to read and understand.

This is the exact system I would personally use if I were to make any horror games that require a flashlight. It’s simple and easy to make. If you want a more in-depth explanation surrounding the code just message me!

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.