Help with Server/Client event process

Hey everyone, i’m currently working on a grip and carry system and it is designed to allow players to interact with other players who are in a “knocked” state.

This system involves two scripts: a ServerScript and a LocalScript.

The ServerScript handles setting a player’s knocked state, handling health restrictions, and listening for the B and C key presses to perform grip or carry actions. The LocalScript complements this by playing animations and sounds on the client side.


The issue here is that the B and C keys, which trigger the grip and carry actions, even after being registered and approved by the server, the animations and sounds aren't firing.

I’ll post the client script, for further clarity. thanks for the help…

1 Like

Local Script :

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Animations = ReplicatedStorage:WaitForChild("Animations")
local Sounds = ReplicatedStorage:WaitForChild("Sounds")
local GripEvent = ReplicatedStorage.Events:WaitForChild("GripEvent")
local CarryEvent = ReplicatedStorage.Events:WaitForChild("CarryEvent")
local UserInputService = game:GetService("UserInputService")
local Player = game.Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local Humanoid = Character:WaitForChild("Humanoid")

local cooldownTime = 1
local lastPressed = 0 

local function ensureBodyAttachment(hrp)
	if not hrp:FindFirstChild("BodyAttachment") then
		Instance.new("Attachment", hrp).Name = "BodyAttachment"
		print("BodyAttachment added to", hrp.Parent.Name)
	end
end

local playerHRP = Character:WaitForChild("HumanoidRootPart")
ensureBodyAttachment(playerHRP)

local function createAlignPosition(victimHRP, playerHRP)
	local alignPosition = Instance.new("AlignPosition")
	alignPosition.Attachment0 = playerHRP:FindFirstChild("BodyAttachment")
	alignPosition.Attachment1 = victimHRP:FindFirstChild("BodyAttachment")
	alignPosition.RigidityEnabled = true
	alignPosition.MaxForce = math.huge
	alignPosition.MaxVelocity = 20
	alignPosition.Parent = victimHRP
	print("AlignPosition created for", victimHRP.Parent.Name)
	return alignPosition
end

local function playGripAnimation(victim)
	print("Playing grip animation for victim:", victim.Name)

	local victimHRP = victim:WaitForChild("HumanoidRootPart")
	ensureBodyAttachment(victimHRP)

	local gripAnimation = Animations:WaitForChild("Grip")
	local victimAnimation = Animations:WaitForChild("BeingGripped")
	Humanoid:LoadAnimation(gripAnimation):Play()
	victim:FindFirstChild("Humanoid"):LoadAnimation(victimAnimation):Play()
	print("Grip animations playing.")

	task.delay(0.3, function()
		Sounds:WaitForChild("Hit"):Play()
		print("Grip sound played.")
	end)

	local alignPosition = createAlignPosition(victimHRP, playerHRP)
	task.delay(5, function()  
		alignPosition:Destroy()
	end)
end

local function playCarryAnimation(victim)
	print("Playing carry animation for victim:", victim.Name)

	local victimHRP = victim:WaitForChild("HumanoidRootPart")
	ensureBodyAttachment(victimHRP)

	local carryAnimation = Animations:WaitForChild("Carry")
	local victimAnimation = Animations:WaitForChild("BeingCarried")
	Humanoid:LoadAnimation(carryAnimation):Play()
	victim:FindFirstChild("Humanoid"):LoadAnimation(victimAnimation):Play()
	print("Carry animations playing.")

	task.delay(0.3, function()
		Sounds:WaitForChild("Splurge2"):Play()
		print("Carry sound played.")
	end)

	local alignPosition = createAlignPosition(victimHRP, playerHRP)
	task.delay(5, function()
		alignPosition:Destroy()
	end)
end

UserInputService.InputBegan:Connect(function(input, isProcessed)
	if isProcessed then return end

	local currentTime = tick()
	if currentTime - lastPressed < cooldownTime then
		return 
	end

	local targetPlayer = nil
	for _, otherPlayer in pairs(game.Players:GetPlayers()) do
		if otherPlayer ~= Player and otherPlayer.Character and otherPlayer.Character:GetAttribute("IsKnocked") then
			targetPlayer = otherPlayer
			print("Target player identified for action:", targetPlayer.Name)
			break
		end
	end

	if input.KeyCode == Enum.KeyCode.B and targetPlayer then
		print("Grip key (B) pressed. Sending request to server.")
		lastPressed = currentTime  
		GripEvent:FireServer(targetPlayer) 
	end

	if input.KeyCode == Enum.KeyCode.C and targetPlayer then
		print("Carry key (C) pressed. Sending request to server.")
		lastPressed = currentTime  
		CarryEvent:FireServer(targetPlayer)  
	end
end)

GripEvent.OnClientEvent:Connect(function(player, victim)
	if player == Player then
		print("Grip event received for player:", player.Name)
		playGripAnimation(victim)
	end
end)

CarryEvent.OnClientEvent:Connect(function(player, victim)
	if player == Player then
		print("Carry event received for player:", player.Name)
		playCarryAnimation(victim)
	end
end)
1 Like

how are you firing the grip event and carry event?

1 Like
  • Server: The server listens for the event from the client (OnServerEvent), processes the action, and fires a response back to the client (FireClient).
  • Client: The client listens for key inputs (grip or carry) and sends the request to the server (FireServer). The server processes the request and fires the event back to the client to trigger the animations and sounds.

– Grip Action (B key)

if input.KeyCode == Enum.KeyCode.B and targetPlayer then
	print("Grip key (B) pressed. Sending request to server.")
	lastPressed = currentTime  
	GripEvent:FireServer(targetPlayer)  
end 

– Carry Action (C key)

if input.KeyCode == Enum.KeyCode.C and targetPlayer then
	print("Carry key (C) pressed. Sending request to server.")
	lastPressed = currentTime  
	CarryEvent:FireServer(targetPlayer)  
end

The issue is that the animations and sounds aren’t firing although the events are set up correctly

1 Like

can you send the server script?

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Sounds = ReplicatedStorage:WaitForChild("Sounds")
local MIN_HEALTH_THRESHOLD = 1
local KNOCKED_DURATION = 50
local PROXIMITY_RADIUS = 10

local GripEvent = ReplicatedStorage.Events:WaitForChild("GripEvent")
local CarryEvent = ReplicatedStorage.Events:WaitForChild("CarryEvent")

local function stopAllActions(character)
	local humanoid = character:FindFirstChild("Humanoid")
	if humanoid then
		humanoid.PlatformStand = true
		humanoid.WalkSpeed = 0
		humanoid.JumpPower = 0
		print("Stopping all actions for", character.Name)
	end
end

local function restoreNormalState(character)
	local humanoid = character:FindFirstChild("Humanoid")
	if humanoid then
		humanoid.PlatformStand = false
		humanoid.WalkSpeed = 16
		humanoid.JumpPower = 50
		print("Restoring normal state for", character.Name)
	end
end

local function applyKnockedState(character)
	local humanoid = character:FindFirstChild("Humanoid")
	if not humanoid then return end
	humanoid.Health = MIN_HEALTH_THRESHOLD

	stopAllActions(character)
	character:SetPrimaryPartCFrame(character.HumanoidRootPart.CFrame * CFrame.new(0, -2, 0))
	character:SetAttribute("IsKnocked", true)

	Sounds.Splurge:Play()
	print("Player knocked:", character.Name)

	wait(KNOCKED_DURATION)

	restoreNormalState(character)
	character:SetAttribute("IsKnocked", false)
	print("Knocked state ended for:", character.Name)
end

local function isPlayerCloseEnough(player, victim)
	local playerHRP = player.Character and player.Character:FindFirstChild("HumanoidRootPart")
	local victimHRP = victim.Character and victim.Character:FindFirstChild("HumanoidRootPart")

	if playerHRP and victimHRP then
		local distance = (playerHRP.Position - victimHRP.Position).Magnitude
		print("Distance between player:", player.Name, "and victim:", victim.Name, "is:", distance)
		print("Proximity radius is set to:", PROXIMITY_RADIUS)

		return distance <= PROXIMITY_RADIUS
	end

	print("Error: Could not find HumanoidRootPart for either player or victim")
	return false
end

local function preventDeath(humanoid)
	humanoid.HealthChanged:Connect(function()
		if humanoid.Health < MIN_HEALTH_THRESHOLD then
			humanoid.Health = MIN_HEALTH_THRESHOLD
		end
	end)
end

GripEvent.OnServerEvent:Connect(function(player, targetPlayer)
	local character = player.Character
	local targetCharacter = targetPlayer.Character

	if character and targetCharacter and targetCharacter:GetAttribute("IsKnocked") then
		if isPlayerCloseEnough(player, targetPlayer) then
			print("Grip action approved. Player:", player.Name, "Victim:", targetPlayer.Name)
			GripEvent:FireClient(player, targetPlayer)
		else
			print("Grip action denied. Target too far.")
		end
	else
		print("Grip action denied. Target is not knocked.")
	end
end)

CarryEvent.OnServerEvent:Connect(function(player, targetPlayer)
	local character = player.Character
	local targetCharacter = targetPlayer.Character

	if character and targetCharacter and targetCharacter:GetAttribute("IsKnocked") then
		if isPlayerCloseEnough(player, targetPlayer) then
			print("Carry action approved. Player:", player.Name, "Victim:", targetPlayer.Name)
			CarryEvent:FireClient(player, targetPlayer)
		else
			print("Carry action denied. Target too far.")
		end
	else
		print("Carry action denied. Target is not knocked.")
	end
end)

Players.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function(character)
		local humanoid = character:WaitForChild("Humanoid")
		preventDeath(humanoid)

		humanoid.HealthChanged:Connect(function()
			if humanoid.Health <= 0 then
				applyKnockedState(character)
			end
		end)
	end)
end)
1 Like

I assume victim is another player? A Player cannot animate another Player’s Animator (when you call Humanoid:LoadAnimation it just calls Humanoid.Animator:LoadAnimation). And, make sure the Priority of the Animation is set to something above Core.

1 Like

btw this check seems kinda pointless aswell btw

	if player == Player then

Is it printing out grip event recieved for player?

you’re right, it checks if the event was triggered by the local player itself, but it’s redundant. The client is only going to listen to the events that it sent to itself, so this check will always be true.

1 Like

You’re on the right track; however, like Judgy_Oreo said, you cannot play animations on another player’s character, the attacker (person doing the grip/carry action) can only manage assemblies that they have network ownership over (namely their own character, and any unanchored parts within a certain distance, any anything else you explicitly give them ownership with using BasePart:SetNetworkOwner.

Two things you can do for this: fire a separate remote event to the VICTIM’s client, which will play that animation on their own character, OR, you can just load and play the animation on the victim’s character directly from the server.

Another issue, but with the same cause, is that you’re trying to manage the physics of another player’s character from the attacker’s client, which once again, isn’t feasible because you don’t have network ownership over it.

To solve that issue, you can create the AlignPosition on the server instead; however, this may or may not appear delayed when you walk around, I’m not certain. What I would personally do is create a clone of the victim and hide the original victim’s character, and then give the attacker network ownership over it and then create the AlignPosition for that clone on the attacker’s client so that it looks accurate on all screens, especially for the attacker.

Now –

I know before I suggested AlignPosition, which is still a good option if you do it right, but you can also loop through the entire assembly of the victim’s character and make it massless, THEN create the Weld on the server between your attacker and the victim. Making their limbs massless means they can no longer keep ownership of their own character when the weld links them together, giving the attacker full network ownership of their character for the period of the carrying. Then, I’d still play the animation on the server to prevent any finnicky replication issues.

Let me know if you need further explanation.

2 Likes

Just be careful if you go the route of welding, replication is really a hit or miss, there are cases where welding two players can cause other issues regardless of Mass, where if either of the welded players die, the other player dies too.

I would also try, for the sake of simplicity, giving the attacker network ownership of the victim’s character by doing victimRootPart:SetNetworkOwner(attackerPlayer) if you do use AlignPosition. That may work and no longer require you to do the whole cloning and invisibility trick.

2 Likes

that was it, i wouldnt have figured it out on my own tbh, this was way harder than i had initially accounted for, although i’m still having issues with synchronizing all the animations now that each one is fired by its own event handler, and also few welding issues to actually make it work as i’d like, but so far this is what i ended up with. Let me know if you have any more inputs into this, THANK you so much, that was insanely helpful.

client script

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Animations = ReplicatedStorage:WaitForChild("Animations")
local Sounds = ReplicatedStorage:WaitForChild("Sounds")
local GripEvent = ReplicatedStorage.Events:WaitForChild("GripEvent")
local CarryEvent = ReplicatedStorage.Events:WaitForChild("CarryEvent")
local PlayerGripEvent = ReplicatedStorage.Events:WaitForChild("PlayerGripEvent")
local PlayerCarryEvent = ReplicatedStorage.Events:WaitForChild("PlayerCarryEvent")
local VictimGripEvent = ReplicatedStorage.Events:WaitForChild("VictimGripEvent")
local VictimCarryEvent = ReplicatedStorage.Events:WaitForChild("VictimCarryEvent")
local UserInputService = game:GetService("UserInputService")
local Player = game.Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local Humanoid = Character:WaitForChild("Humanoid")

local cooldownTime = 1
local lastPressed = 0 

local function ensureBodyAttachment(hrp)
	if not hrp:FindFirstChild("BodyAttachment") then
		local attachment = Instance.new("Attachment", hrp)
		attachment.Name = "BodyAttachment"
		print("BodyAttachment added to", hrp.Parent.Name)
	end
end

local playerHRP = Character:WaitForChild("HumanoidRootPart")
ensureBodyAttachment(playerHRP)

local function createAlignPosition(victimHRP, playerHRP)
	local alignPosition = Instance.new("AlignPosition")
	alignPosition.Attachment0 = playerHRP:FindFirstChild("BodyAttachment")
	alignPosition.Attachment1 = victimHRP:FindFirstChild("BodyAttachment")
	alignPosition.RigidityEnabled = true
	alignPosition.MaxForce = math.huge
	alignPosition.MaxVelocity = 20
	alignPosition.Parent = victimHRP
	print("AlignPosition created for", victimHRP.Parent.Name)
	return alignPosition
end

local function playGripAnimation(victim)
	print("Playing grip animation for victim:", victim.Name)

	local victimHRP = victim:WaitForChild("HumanoidRootPart")
	ensureBodyAttachment(victimHRP)

	local gripAnimation = Animations:FindFirstChild("Grip")
	local victimAnimation = Animations:FindFirstChild("BeingGripped")

	if gripAnimation and victimAnimation then
		Humanoid:LoadAnimation(gripAnimation):Play()
		victim:FindFirstChild("Humanoid"):LoadAnimation(victimAnimation):Play()
		print("Grip animations playing.")

		task.delay(0.3, function()
			Sounds:WaitForChild("Hit"):Play()
			print("Grip sound played.")
		end)

		local alignPosition = createAlignPosition(victimHRP, playerHRP)
		task.delay(5, function()
			alignPosition:Destroy()
		end)
	else
		warn("Grip or victim animation missing")
	end
end

local function playCarryAnimation(victim)
	print("Playing carry animation for victim:", victim.Name)

	local victimHRP = victim:WaitForChild("HumanoidRootPart")
	ensureBodyAttachment(victimHRP)

	local carryAnimation = Animations:FindFirstChild("Carry")
	local victimAnimation = Animations:FindFirstChild("BeingCarried")

	if carryAnimation and victimAnimation then
		Humanoid:LoadAnimation(carryAnimation):Play()
		victim:FindFirstChild("Humanoid"):LoadAnimation(victimAnimation):Play()
		print("Carry animations playing.")

		task.delay(0.3, function()
			Sounds:WaitForChild("Splurge2"):Play()
			print("Carry sound played.")
		end)

		local alignPosition = createAlignPosition(victimHRP, playerHRP)
		task.delay(5, function()
			alignPosition:Destroy()
		end)
	else
		warn("Carry or victim animation missing")
	end
end

UserInputService.InputBegan:Connect(function(input, isProcessed)
	if isProcessed then return end

	local currentTime = tick()
	if currentTime - lastPressed < cooldownTime then return end

	local targetPlayer
	for _, otherPlayer in pairs(game.Players:GetPlayers()) do
		if otherPlayer ~= Player and otherPlayer.Character and otherPlayer.Character:GetAttribute("IsKnocked") then
			targetPlayer = otherPlayer
			print("Target player identified for action:", targetPlayer.Name)
			break
		end
	end

	if input.KeyCode == Enum.KeyCode.B and targetPlayer then
		print("Grip key (B) pressed. Sending request to server.")
		lastPressed = currentTime
		GripEvent:FireServer(targetPlayer)
	elseif input.KeyCode == Enum.KeyCode.C and targetPlayer then
		print("Carry key (C) pressed. Sending request to server.")
		lastPressed = currentTime
		CarryEvent:FireServer(targetPlayer)
	end
end)

PlayerGripEvent.OnClientEvent:Connect(function(_, victim)
	print("Grip event received for player.")
	playGripAnimation(victim)
end)

PlayerCarryEvent.OnClientEvent:Connect(function(_, victim)
	print("Carry event received for player.")
	playCarryAnimation(victim)
end)

VictimGripEvent.OnClientEvent:Connect(function()
	print("Playing victim's grip animation.")
	playGripAnimation(Player.Character)
end)

VictimCarryEvent.OnClientEvent:Connect(function()
	print("Playing victim's carry animation.")
	playCarryAnimation(Player.Character)
end)

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