Animations & Emote Handler - Efficient?

Hii! So I have scripted this animations & emote handler recently and I wanted to ask if this is efficient enought for a 50 player based game:

local AnimationsHandler = {}

local loadedAnims = {}
local runningEmotes = {}
local seats

local animations = {	
}

local DuoEmotes = {
}

local seats = game.Workspace:WaitForChild("AnimSeats")

for i,v in animations do
	local newAnimation = Instance.new("Animation")
	newAnimation.AnimationId = "rbxassetid://"..v
	--newAnimation.Parent = script
	newAnimation.Name = i
	animations[i] = newAnimation
end

for i,v in DuoEmotes do
	for name,ID in v do
		if typeof(ID) == "number" then
			local newAnimation = Instance.new("Animation")
			newAnimation.AnimationId = "rbxassetid://"..ID
			--newAnimation.Parent = script
			newAnimation.Name = name
			DuoEmotes[i][name] = newAnimation
		end
	end
end

-- BEGIN

AnimationsHandler.CancelAllEmotes = function(player)
	if runningEmotes[player] then -- Incase emote was already playing + In case duo emote was playing
		if DuoEmotes[runningEmotes[player]] then
			AnimationsHandler.StopAnimation(player,runningEmotes[player],"Idle")
		else
			AnimationsHandler.StopAnimation(player,runningEmotes[player])
		end
		runningEmotes[player] = ""
	end
end

AnimationsHandler.PlayEmote = function(player,name,RemoveUponMoving)
	if loadedAnims[player][name] then
		AnimationsHandler.CancelAllEmotes(player)
		AnimationsHandler.PlayAnimation(player,name)
		runningEmotes[player] = name
		if RemoveUponMoving then
			AnimationsHandler.CreateMovingListener(player,name)
		end
	end
end

AnimationsHandler.PlayDuoEmote = function(player,name)
	if loadedAnims[player].DuoEmotes[name] then
		AnimationsHandler.CancelAllEmotes(player)
		AnimationsHandler.RunDuoEmote(player,name,"Idle")
		runningEmotes[player] = name
		AnimationsHandler.CreateMovingListener(player,name,"Idle")
		
		local newProxi = script.PerformDuo:Clone()
		newProxi.Parent = player.Character.HumanoidRootPart
		
		game.ReplicatedStorage.Assets.Remotes.Emotes.HideDuoPrompt:FireClient(player,newProxi)
		
		newProxi.Triggered:Connect(function(player2)
			
			if player2.Character.Humanoid.Sit == false then
				AnimationsHandler.DepcrecateListener(player,name)
				AnimationsHandler.StopAnimation(player,name,"Idle")
				
				if runningEmotes[player] then
					if runningEmotes[player] then
						runningEmotes[player] = nil
					end
				end
				
				AnimationsHandler.CancelAllEmotes(player2)
				
				player2.Character.HumanoidRootPart.Anchored = true
				player.Character.HumanoidRootPart.Anchored = true
				
				--task.wait(0.5)
				
				DuoEmotes[name].TPFunction(player,player2)
				
				AnimationsHandler.RunDuoEmote(player,name,"PlayerOne")
				AnimationsHandler.RunDuoEmote(player2,name,"PlayerTwo")
				
				task.spawn(function()
					task.wait(loadedAnims[player].DuoEmotes[name].PlayerOne.Length)
					player.Character.HumanoidRootPart.Anchored = false
				end)
				
				task.spawn(function()
					task.wait(loadedAnims[player2].DuoEmotes[name].PlayerTwo.Length)
					player2.Character.HumanoidRootPart.Anchored = false
					player2.Character.HumanoidRootPart.CFrame = player.Character.HumanoidRootPart.CFrame + CFrame.new(0,5,0)
				end)
				
			end
		end)
		
	end
end

AnimationsHandler.RunDuoEmote = function(player,emote,extra)
	if loadedAnims[player].DuoEmotes[emote] then
		loadedAnims[player].DuoEmotes[emote][extra]:Play()
		loadedAnims[player].Current = extra
	end
end

AnimationsHandler.PlayAnimation = function(player,name,extra)
	if extra then
		if loadedAnims[player][name] then
			if loadedAnims[player][name][extra] then
				loadedAnims[player][name][extra]:Play()
				loadedAnims[player].Current = extra
			end
		end
	else
		if loadedAnims[player][name] then
			loadedAnims[player][name]:Play()
			loadedAnims[player].Current = name
		end
	end
end

AnimationsHandler.StopAnimation = function(player,name,extra)
	if extra then
		if loadedAnims[player].DuoEmotes[name] then
			loadedAnims[player].DuoEmotes[name][extra]:Stop()
			loadedAnims[player].Current = ""
			player.Character.HumanoidRootPart.PerformDuo:Destroy()
			AnimationsHandler.DepcrecateListener(player,name)
		end
	else
		if loadedAnims[player][name] then
			loadedAnims[player][name]:Stop()
			loadedAnims[player].Current = ""
			AnimationsHandler.DepcrecateListener(player,name)
		end
	end
end

AnimationsHandler.DepcrecateListener = function(player,name)
	if loadedAnims[player].Listeners[name] then
		loadedAnims[player].Listeners[name]:Disconnect()
		loadedAnims[player].Listeners[name] = nil
	end
end

AnimationsHandler.CreateMovingListener = function(plr,loadedAnimation,extra)
	local char = plr.Character
	local humanoid = char.Humanoid
	
	local debounce = false
	
	--loadedAnims[plr].TotalListeners += 1
	local i = loadedAnims[plr].TotalListeners
	
	if extra then
		loadedAnims[plr].Listeners[loadedAnimation] = char.Humanoid.Changed:Connect(function()
			if debounce == false then
				if humanoid.Jump == true or humanoid.MoveDirection ~= Vector3.new(0,0,0) then
					debounce = true
					loadedAnims[plr].Listeners[loadedAnimation]:Disconnect()
					loadedAnims[plr].Listeners[loadedAnimation] = nil
					AnimationsHandler.StopAnimation(plr,loadedAnimation,extra)
					if runningEmotes[plr] then
						if runningEmotes[plr] then
							runningEmotes[plr] = nil
						end
					end
				end
			end
		end)
	else
		loadedAnims[plr].Listeners[loadedAnimation] = char.Humanoid.Changed:Connect(function()
			if debounce == false then
				if humanoid.Jump == true or humanoid.MoveDirection ~= Vector3.new(0,0,0) then
					debounce = true
					loadedAnims[plr].Listeners[loadedAnimation]:Disconnect()
					loadedAnims[plr].Listeners[loadedAnimation] = nil
					AnimationsHandler.StopAnimation(plr,loadedAnimation)
					if runningEmotes[plr] then
						if runningEmotes[plr] then
							runningEmotes[plr] = nil
						end
					end
				end
			end
		end)
	end
end

AnimationsHandler.SeatListener = function()
	for _,seat in seats:GetDescendants() do
		if seat:IsA("Seat") then
			if seat:FindFirstChildWhichIsA("ProximityPrompt") then
				seat:FindFirstChildWhichIsA("ProximityPrompt").Triggered:Connect(function(plr)
					if seat.Occupant == nil then
						seat:Sit(plr.Character.Humanoid)
						AnimationsHandler.CancelAllEmotes(plr)
						AnimationsHandler.PlayAnimation(plr,seat.Name)
						AnimationsHandler.CreateMovingListener(plr,seat.Name)
					end
				end)
			end
		end
	end
end

AnimationsHandler.PlayerRemoved = function(plr)
	if runningEmotes[plr] then
		runningEmotes[plr] = nil
	end
	if loadedAnims[plr].Listeners then
		for _,v in loadedAnims[plr].Listeners do
			v:Disconnect()
			v = nil
		end
		loadedAnims[plr] = nil
	end
end

AnimationsHandler.Animations = function()
	return animations
end

AnimationsHandler.DuoEmotes = function()
	return DuoEmotes
end

AnimationsHandler.CharacterAdded = function(char)
	local plr = game.Players:GetPlayerFromCharacter(char)
	char:WaitForChild("Humanoid"):WaitForChild("Animator")
	
	if loadedAnims[plr] then
		for _,v in loadedAnims[plr].Listeners do
			v:Disconnect()
		end
		for i,v in loadedAnims[plr] do
			if i == "Listeners" or i == "Current" or i == "TotalListeners" then continue end
			if i == "DuoEmotes" then
				for _,v2 in v do
					for _,v3 in v2 do
						v3:Destroy()
					end
				end
			else
				v:Destroy()
			end
		end
	end
	
	loadedAnims[plr] = {
		["Listeners"] = {
			
		},
		
		["Current"] = {
			
		},
		
		["TotalListeners"] = 0,
		
		["DuoEmotes"] = {
			
		},
	}
	
	for i,v in animations do
		loadedAnims[plr][i] = char.Humanoid.Animator:LoadAnimation(v)
	end
	
	for i,v in DuoEmotes do
		loadedAnims[plr].DuoEmotes[i] = {}
		for name,ID in v do
			if name == "TPFunction" then continue end
			if ID:IsA("Animation") then
				loadedAnims[plr].DuoEmotes[i][name] = char.Humanoid.Animator:LoadAnimation(ID)
			end
		end
	end
	
	local currentToolConnection
	
	char.ChildAdded:Connect(function(child)
		if child:IsA("Tool") then
			if loadedAnims[plr][child.Name] then
				currentToolConnection = child.Activated:Connect(function()
					if child:GetAttribute("OnDebounce") == true then return nil end
					child:SetAttribute("OnDebounce",true)
					task.spawn(function()
						task.wait(loadedAnims[plr][child.Name].Length)
						child:SetAttribute("OnDebounce",nil)
					end)
					AnimationsHandler.PlayAnimation(plr,child.Name)
				end)
			end
		end
	end)

	char.ChildRemoved:Connect(function(child)
		if currentToolConnection and child:IsA("Tool") then
			currentToolConnection:Disconnect()
			currentToolConnection = nil
			AnimationsHandler.StopAnimation(plr,child.Name)
			child:SetAttribute("OnDebounce",nil)
		end
	end)
end

AnimationsHandler.SeatListener()

return AnimationsHandler

I have taken out all of the emotes, just incase you are wondering.

At a game, to do it optimized, you need to avoid much loops, and when doing it, place a task.wait(…) do make it light

As it seems that the script is unique, and everything is placed carefully, it seems well optimized to what you want.

1 Like

Thank you for your reply! I appreciate it by alot! :slight_smile: