- 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.
- 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)
- 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.