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.
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)
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
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.
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
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!