I was really curious how it is possible to make Automatic Syncing.
As in →
If a player syncs with someone, it will automatically dance them to the player. Though if the player that is being synced with CHANGES their dance, it will AUTOMATICALLY change the person syncing with that one player dance.
For instance →
/sync (name) ← this will sync you with player and keep you syncing with them until you do -
/unsync
What is the issue?
I can’t figure out how it is possible to keep the player syncing with the other player, if they change their dance.
What solutions have you tried so far?
I HAVE A FULLY WORKING SYNC SYSTEM ALREADY.
Only issue, is I haven’t added the detection to automatically sync them if they change the dance, and they are still synced up with someone.
I was going about with this idea →
When a player joins the game :
local SyncValue = Instance.new("StringValue") -- Creating String Value
SyncValue.Name = "SyncValue"
SyncValue.Parent = localplr
SyncValue.Value = nil -- Default Nil
When the player does /sync :
if player2 and player2:IsA("Player") then
SyncValue.Value = player2.Name -- Sync Value set to Player Name
require(script.ModuleSync):Sync(localplr,player2)
end
When the player does /unsync :
SyncValue.Value = nil -- Sync Value set to Default
How could I go about, checking if the value is the targets name and seeing if it changes. If the player2 changes their dance, then it will change the player1 dance as will (IF THEY ARE STILL IN SYNC).
Would this be done using WhileTrueDo in another script? My knowledge is short on this.Could this help?
I would have a SyncValue, being in the player that got synced, and have the value being the player that syncs to that player.
I would probably be using Animator.AnimationPlayed to detect animation playing, and then stop the animation the player that sync is currently playing, and instead replace them with the animation track Animator.AnimationPlayed returned.
-- Player that got sync's Animator
Animator.AnimationPlayed:Connect(function(animationtrack) -- fire when new animation played
if Player.SyncValue.Value then -- check if anyone is syncing to this person
local player = Player:FindFirstChild(SyncValue.Value) -- find synched player
if player and player.Character then -- check if there is character
local syncAnimator = player.Character.Humanoid.Animator -- animator of synched person
for _,v in ipairs(syncAnimator:GetPlayingAnimationTracks()) do -- stopping all animation
v:Stop()
end
syncAnimator:LoadAnimation(animationtrack.Animation):Play()
end
end
end)
It should be if the priority is the same or higher but just in case. Stopping all the animation is probably not needed and you could remove that if you want.
--SERVER
local players = game:GetService("Players")
local replicated = game:GetService("ReplicatedStorage")
local remote = replicated.RemoteEvent
local function onPlayerAdded(player)
local sync = Instance.new("ObjectValue")
sync.Name = "Sync"
sync.Parent = player
local function onPlayerChatted(message)
local splitMessage = message:lower():split(" ")
if #splitMessage >= 2 then
if splitMessage[1]:match("^/sync$") then
local syncedPlayers = {}
for _, otherPlayer in ipairs(players:GetPlayers()) do
if otherPlayer ~= player then
if otherPlayer.Name:lower():match(splitMessage[2]) then
table.insert(syncedPlayers, otherPlayer)
end
end
end
if #syncedPlayers == 1 then
local syncedPlayer = syncedPlayers[1]
sync.Value = syncedPlayer
end
end
end
end
local function onCharacterAdded(character)
local function onAnimationPlayed(animationTrack)
for _, syncedPlayer in ipairs(players:GetPlayers()) do
if syncedPlayer ~= player then
if syncedPlayer.Sync.Value == player then
local syncedCharacter = syncedPlayer.Character
local syncedHumanoid = syncedCharacter.Humanoid
if syncedHumanoid.Health > 0 then
print(animationTrack.Animation)
remote:FireClient(syncedPlayer, animationTrack.Animation.AnimationId)
end
end
end
end
end
local humanoid = character:WaitForChild("Humanoid")
local animator = humanoid:WaitForChild("Animator")
animator.AnimationPlayed:Connect(onAnimationPlayed)
end
player.Chatted:Connect(onPlayerChatted)
player.CharacterAdded:Connect(onCharacterAdded)
end
players.PlayerAdded:Connect(onPlayerAdded)
--LOCAL
local replicated = game:GetService("ReplicatedStorage")
local remote = replicated:WaitForChild("RemoteEvent")
local players = game:GetService("Players")
local player = players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
local animator = humanoid:WaitForChild("Animator")
local animation = Instance.new("Animation")
local function onRemoteFired(animationId)
animation.AnimationId = animationId
local animationTrack = animator:LoadAnimation(animation)
repeat task.wait() until animationTrack.Length > 0
animationTrack:Play()
end
remote.OnClientEvent:Connect(onRemoteFired)
I just wrote this system which achieves this (shared/synced animations). This implementation makes use of a single RemoteEvent instance placed inside the ReplicatedStorage folder.
This seems to be a great fix to this, though how am I able to make them /unsync? I tried importing this into my code, and having troubles. Seems like the sync is working but its still not playing the animations correctly.
StarterPlayerScripts -
--[[ ENABLE GUI ]]--
local StarterGui = game:GetService("StarterGui") -- StarterGui
StarterGui:SetCore("AvatarContextMenuEnabled", true) -- Enabling AvatarContextMenu
StarterGui:SetCore("RemoveAvatarContextMenuOption", Enum.AvatarContextMenuOption.Emote) -- Disabling AvatarContextMenuEmote
--[[ GUI FUNCTION ]]--
local be = Instance.new("BindableEvent") -- New Event
local function sync(t) -- New Function To Fire Server (Sync)
game.ReplicatedStorage.EVENTS:FindFirstChild("Sync"):FireServer(t)
end
be.Event:Connect(sync) -- Fires server when clicked
--[[ CREATING SYNC CURRENT DANCE BUTTON ]]--
StarterGui:SetCore("AddAvatarContextMenuOption", {"Sync Current Dance", be}) -- Adding Sync Dance Context
local replicated = game:GetService("ReplicatedStorage")
local remote = replicated.EVENTS:WaitForChild("NewSync")
local players = game:GetService("Players")
local player = players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
local animator = humanoid:WaitForChild("Animator")
local animation = Instance.new("Animation")
local function onRemoteFired(animationId)
animation.AnimationId = animationId
local animationTrack = animator:LoadAnimation(animation)
repeat task.wait() until animationTrack.Length > 0
animationTrack:Play()
end
remote.OnClientEvent:Connect(onRemoteFired)
ServerScriptService -
--[[
@author TwinPlayzDev_YT
@since 2/21/2022
This script will let players sync animations with other players.
Place this script in ServerScriptService.
--]]
--[ SERVICES ]--
local Players = game:GetService("Players")
--[ MAIN LOCALS ]--
local PlayerUsage = {} -- Player Table
local syncedPlayers = {}
local player2
local replicated = game:GetService("ReplicatedStorage")
local remote = replicated.EVENTS.NewSync
--[ FUNCTIONS ]--
game.Players.PlayerAdded:Connect(function(localplr)
local sync = Instance.new("ObjectValue")
sync.Name = "Sync"
sync.Parent = localplr
coroutine.resume(coroutine.create(function()
localplr.Chatted:Connect(function(msg)
local lowerString = string.lower(msg)
local args = string.split(lowerString," ")
if args[1] == "/sync" then
for _, otherPlayer in ipairs(Players:GetPlayers()) do
if otherPlayer ~= localplr then
if otherPlayer.Name:match(args[2]) then
table.insert(syncedPlayers, otherPlayer)
require(script.ModuleSync):Sync(localplr,otherPlayer)
end
end
end
if #syncedPlayers == 1 then
local syncedPlayer = syncedPlayers[1]
sync.Value = syncedPlayer
end
elseif args[1] == "/unsync" then
for _, otherPlayer in ipairs(Players:GetPlayers()) do
if otherPlayer ~= localplr then
if otherPlayer.Name:match(args[2]) then
table.remove(syncedPlayers, otherPlayer)
end
end
end
end
end)
end))
local function onCharacterAdded(character)
local function onAnimationPlayed(animationTrack)
for _, syncedPlayer in ipairs(Players:GetPlayers()) do
if syncedPlayer ~= localplr then
if syncedPlayer.Sync.Value == localplr then
local syncedCharacter = syncedPlayer.Character
local syncedHumanoid = syncedCharacter.Humanoid
if syncedHumanoid.Health > 0 then
print(animationTrack.Animation)
remote:FireClient(syncedPlayer, animationTrack.Animation.AnimationId)
end
end
end
end
end
local humanoid = character:WaitForChild("Humanoid")
local animator = humanoid:WaitForChild("Animator")
animator.AnimationPlayed:Connect(onAnimationPlayed)
end
localplr.CharacterAdded:Connect(onCharacterAdded)
end)
game.ReplicatedStorage.EVENTS.Sync.OnServerEvent:Connect(function(player, player2)
if player2 and player2:IsA("Player") then
table.insert(syncedPlayers, player)
local syncValue = player:FindFirstChild("Sync")
if #syncedPlayers == 1 then
local syncedPlayer = syncedPlayers[1]
syncValue.Value = syncedPlayer
end
local now = tick()
local LastUsed = PlayerUsage[player] or 0
if now - LastUsed > 3 then
PlayerUsage[player] = now
require(script.ModuleSync):Sync(player,player2)
end
end
end)