Animations interfering with a RemoteEvent fired via a bound action using ContextActionService

  1. What do I want to achieve?

I want to use a Client-To-Server remote event to stop animations that were played (for the player) ON the server. I have since realized that this remote event, though triggering, is not properly working. My current guess as to why this is the case is because an action I bound using ContextActionService is triggering a remote event before animations can stop playing and subsequent code can run.

  1. What is the issue?

The issue is that despite my code looking correct, and me seeing no issues with it, often-times, the animations do not stop when calling the :Stop() method via the aforementioned RemoteEvent. In addition to that, other code executes. It is somewhat hard to explain.

Here is a video example of what I mean. Keep in mind that when the ProximityPrompt is triggered, the movement of the player is restricted while several animations play. One walks the player towards a location, one picks up a tool, one positions said tool, and the final animation, which is looped, is a constant wood chopping animation. However, if the player presses e, the animations end and player movement is restored.

Here is the video of the unexpected behavior:

Example.wmv (1.7 MB)

In the first part of this video, I provide adequate enough time between inputs to showcase how I want the system to work in its infancy. Then, after the ProximityPrompt is re-enabled, instead of using the e key once, I doubletap it, giving the behavior I am attempting to fix.

I believe I know why this is happening, but I would appreciate some help in fixing this. Here is the code that runs after ProximityPrompt is triggered, it is located in a ServerSide ModuleScript.

function Tree:gatherResource(player, humanoid, activityClone, tool, walkPart, lookPart, prompt)
	-- Disable the proximity prompt
	prompt.Enabled = false
	
	-- Tools
	local axe						= tool.Handle
	local axePosition				= axe.Position
	local axeOrientation			= axe.Orientation
	local axeCFrame					= CFrame.new(axePosition) * CFrame.Angles(math.rad(axeOrientation.X), math.rad(axeOrientation.Y), math.rad(axeOrientation.Z))

	-- SFX
	local axeHit = axe.Parent.Chop; axeHit.Looped	= false
	
	-- Move the humanoid
	movementEvent:FireClient(player, true)
	moveHumanoid(humanoid, walkPart, lookPart)
	
	-- Implement the logic for gathering wood here
	local pickUpAxe = humanoid:LoadAnimation(animationInstances.pickUpAxe)
	local positionAxe = humanoid:LoadAnimation(animationInstances.positionAxe)
	local chopWood = humanoid:LoadAnimation(animationInstances.chopWood)
	
	--Pick up the axe
	pickUpAxe:Play()
	pickUpAxe.Looped = false
	pickUpAxe:GetMarkerReachedSignal("PickUpAxe"):Connect(function()
		axe.Anchored = false
		axe.Parent.Parent = player.Character
		axe.CanCollide = false
	end)
	pickUpAxe.Stopped:Wait()
	
	--Position the axe
	positionAxe:Play()
	positionAxe.Looped = false
	positionAxe.Stopped:Wait()
	
	-- Chop wood
	chopWood:Play()
	chopWood:GetMarkerReachedSignal("AxeSound"):Connect(function()
		axeHit:Play()
	end)
	
	endHarvestEvent.OnServerEvent:Connect(function(player)
		
		pickUpAxe:Stop(.5)
		positionAxe:Stop(.5)
		chopWood:Stop(.5)
		
		tool.Parent = activityClone
		tool:PivotTo(axeCFrame)
		axe.Anchored = true
		axe.CanCollide = true
		
		if player.PlayerGui.ScreenGui:FindFirstChild("InstructionText") then
			local textLabel = player.PlayerGui.ScreenGui:FindFirstChild("InstructionText")
			local Tween = TS:Create(textLabel, tweenInfo1, {TextTransparency = 1})
			Tween:Play()
			task.wait(1)
			textLabel:Destroy()
		else
			
		end
		
		task.wait(2)
		prompt.Enabled = true
		
	end)
	
end

A large majority of the above script is just defining variables and playing animations, but I felt it necessary to include. Here is the other relevant script, it is located in a client-side ModuleScript.

function Movement.Start(state : boolean)
	local function handleAction(actionName, inputState, inputObject)
		if actionName == "StopW" or actionName == "StopS" or actionName == "StopA" or actionName == "StopD" or actionName == "StopSpace" then
			if inputState == Enum.UserInputState.Begin then

			else

			end
		elseif actionName == "StopE" then
			if inputState == Enum.UserInputState.Begin then
				if not Movement.debounceVar then
					Movement.debounceVar = not Movement.debounceVar
					Movement.Start(false)
					endHarvestEvent:FireServer()
					task.wait(2)
					Movement.debounceVar = not Movement.debounceVar
				else
					print("debounce active, please wait!")
				end
			end
		end

	end
	
	if state == true then
		CAS:BindAction("StopW", handleAction, true, Enum.KeyCode.W)
		CAS:BindAction("StopS", handleAction, true, Enum.KeyCode.S)
		CAS:BindAction("StopA", handleAction, true, Enum.KeyCode.A)
		CAS:BindAction("StopD", handleAction, true, Enum.KeyCode.D)
		CAS:BindAction("StopSpace", handleAction, true, Enum.KeyCode.Space)
		CAS:BindAction("StopE", handleAction, true, Enum.KeyCode.E)
	else
		CAS:UnbindAction("StopW")
		CAS:UnbindAction("StopS")
		CAS:UnbindAction("StopA")
		CAS:UnbindAction("StopD")
		CAS:UnbindAction("StopSpace")
		CAS:UnbindAction("StopE")
	end
	
end

movementEvent.OnClientEvent:Connect(function(state)
	Movement.Start(state)
end)
  1. What solutions have I tried thus far

Honestly, I am unsure how to solve this issue. I have tried adding plenty of wait statements, thinking maybe that might be what is causing it, as well as debounce, but because I realized it is linked to the action “StopE” triggering the endHarvestEvent in the other script, I am starting to think this is not the solution I need. I have tried stopping the animations in various ways too, delaying the re-enabling of the Prompt, but as stated earlier, I do not think it is the problem.

Any help is appreciated, thanks in advance.

1 Like