Can i play an animation on another player locally

is this possible, i want to play emotes on everyone locally so i can use animation events to sync music with it

2 Likes

Yes! You can use a RemoteEvent on the server and use the method :FireAllClients() to receive data and trigger logic on the client. You’d want to send over the emoting character and an identifier to tell every client what emote you want to play.

I presume the way it works is you have a player start an emote on their client, in which case you’d need to trigger another RemoteEvent on the server from that player’s client. Be a little careful here though, you don’t want it to be possible for a hacker to overload/crash players in the server by spamming the event.

On the client, you’ll need a localscript to receive this ReplicateEmote notification. From there, you can load the animation and audio, then perform the emote once both the animation and audio have loaded.

If you’re simply trying to play an animation with audio at the exact same time, theoretically they will only be desynced the first time the emote is used (*dependant on internet speed), as the animation/audio have not been downloaded to memory yet, and one may take longer to load than the other. Once they’re both loaded, they should both play immediately and thus in sync.

2 Likes

Just fire it to the client when you want to cancel it and keep the animation track cached on the client so you can retrieve it when you want to cancel

Client script:

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

local syncAnimationRemote = ReplicatedStorage:WaitForChild("SyncAnimation")

local player = Players.LocalPlayer
local cachedAnimationTracks = {} :: { [number]: AnimationTrack } -- {[animationId]: AnimationTrack}

-- replace this with your custom AnimationController system if it works better for you
local function getAnimator(): Animator?
	local character = player.Character
	local humanoid = if character then character:FindFirstChildOfClass("Humanoid") else nil
	local animator = if humanoid then humanoid:FindFirstChildOfClass("Animator") else nil

	return animator
end

-- true state means it should play the animation, false means it should stop
local function onSyncAnimationEvent(state: boolean, animationId: number)
	local animator = getAnimator()
	if not animator then
		return
	end

	local cachedAnimationTrack = cachedAnimationTracks[animationId]
	if not cachedAnimationTrack then
		local animation = Instance.new("Animation")
		animation.AnimationId = `rbxassetid://{animationId}`
		local animationTrack = animator:LoadAnimation(animation)
		cachedAnimationTracks[animationId] = animationTrack
		cachedAnimationTrack = animationTrack
	end

	if not cachedAnimationTrack then
		return
	end

	if state == true then
		animator:PlayAnimation(cachedAnimationTrack)
		return
	end
	if cachedAnimationTrack.IsPlaying then
		animator:StopAnimation(cachedAnimationTrack)
	end
end

local function resetCachedAnimations()
	cachedAnimationTracks = {}
end

syncAnimationRemote.OnClientEvent:Connect(onSyncAnimationEvent)
player.CharacterAdded:Connect(resetCachedAnimations)
player.CharacterRemoving:Connect(resetCachedAnimations)

Server script:

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

local syncAnimationRemote = ReplicatedStorage:FindFirstChild("SyncAnimation") or Instance.new("RemoteEvent")
syncAnimationRemote.Name = "SyncAnimation"
syncAnimationRemote.Parent = ReplicatedStorage

local function playAnimationForPlayer(player: Player, animationId: number)
	if player and player.Character then
		syncAnimationRemote:FireClient(player, true, animationId)
	end
end

local function stopAnimationForPlayer(player: Player, animationId: number)
	if player and player.Character then
		syncAnimationRemote:FireClient(player, false, animationId)
	end
end

local function playAnimationForAll(animationId: number)
	for _, player in Players:GetPlayers() do
		playAnimationForPlayer(player, animationId)
	end
end

local function stopAnimationForAll(animationId: number)
	for _, player in Players:GetPlayers() do
		stopAnimationForPlayer(player, animationId)
	end
end

local function triggerEmoteWithMusic(animationId: number, duration: number)
	playAnimationForAll(animationId)
	task.wait(duration)
	stopAnimationForAll(animationId)
end

Players.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function(character)
		local sampleAnimationId = 1234567890 -- replace with your animation ID
		local duration = 4 -- replace with your animation duration
		triggerEmoteWithMusic(sampleAnimationId, duration)
	end)
end)

Yep I just coded one, check this out!

BUTTON SCRIPT - Put under your TextButton.

local rep = game:GetService('ReplicatedStorage')
local PlayAnimation = rep:WaitForChild('PlayAnimation')
local button = script.Parent

local animationid = "rbxassetid://8463051688"


button.Activated:Connect(function()
	PlayAnimation:FireServer(animationid)
end)

SERVER SCRIPT:

local PlayAnimation = game.ReplicatedStorage:WaitForChild('PlayAnimation')
local PlayAnimationToAllClients = game.ReplicatedStorage:WaitForChild('PlayAnimationToAllClients')

PlayAnimation.OnServerEvent:Connect(function(player, animationid)
	PlayAnimationToAllClients:FireAllClients(animationid)
end)

StarterCharacterScripts, - AnimationScript


local rep = game:GetService('ReplicatedStorage')

local PlayAnimationToAllClients = rep:WaitForChild('PlayAnimationToAllClients')

local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
local animator = humanoid:WaitForChild('Animator')




PlayAnimationToAllClients.OnClientEvent:Connect(function(animationid)
	local SwingAnimation = Instance.new("Animation")
	SwingAnimation.AnimationId = animationid
	
	local SwingAnimationTrack = humanoid:LoadAnimation(SwingAnimation)
	
	SwingAnimationTrack:Play()
	
	SwingAnimationTrack:GetMarkerReachedSignal("SwingEnd"):Connect(function(paramString)
		print(paramString)
	end)
		
end)

WORKSPACE

Note, my animation will not work, as in it’s my animation and it’s private. You have to make your own. But hope this helps!