I want to add a Animation Instance to a table inside a script; then be able to read the keyframes of the animation to fire a function at a certain point of the animation.
My issue is, every time I try this; the connection comes back nil on the first attempt. This makes the entire function break.
When the event Variables.RemoteEvents.CommunicatorEvent:FireServer("Server Animation Finder","With Puck","PowerStop",false), it calls to the server to get the AnimationId, name and so on; then fires the same event to the Client to play the Animation on the client side. That’s what the Client Animation Player is for.
It plays the Animation, and adds the instance to the table.
I am, however I store all the Animation Info on the Server; including its speed, which type of Character Rig, etc… My issue is, I have to add the instances to a table on the local script for me to be able to pause them, and play them properly; but when i try to connect to these instances after they’re added; they don’t connect.
But why? Can’t you just have the client know all the information about the animation by having it in ReplicatedStorage or something? This type of programming just introduces annoying race conditions like this.
Yes, however I’d like to prevent exploiters from messing with the Module Script and editing… as I have the speeds stored on the Module… if they edit that; it will effect all players as it would be visible to all clients.
With this, I still have to add the instance to a table either way to show the animation loaded.
But they can’t replicate to anything that can’t be physically simulated, i.e. they can’t edit animations, values, server-scripts, workspace properties etc.
This type of visual stuff should be visible to the client directly, to prevent input lag etc.
I have to reference Humanoid.Animator:LoadAnimation(NewAnimation) for whatever animation i’m trying to edit, so that way I’m able to pause, and stop an animation; in a different function , or argument.
A good example of this would be, if you want someone to hold a sword up in an animation and hold it while their mouse button 1 is held down, then when the mouse button is released; you have to send that load animation info to the InputEnded function to break the other animation, and play another/ or continue the animation to strike the enemy.
The issue with this is, the game I’m working on is to be competitive. So if the person has an animation speed of .1 for shooting a Hockey Puck, that’ll give them an advantage; which will likely disinterest people from playing the game.
I may end up putting the Info of the animations on the Client, however I’d still have the same issue.
They already have that advantage? The client is still the one telling the server when the hockey puck should actually hit the puck and fling it, it would be no different in that specific example.
You shouldn’t be tying core gameplay features to animations on the client in a competitive game, if it’s so competitive then the server should be the one monitoring the animation and the client should just be loading it in and playing it for the looks.
I’m not sure what you’re trying to say here, but you can just call :Stop.
None of this is improving your game’s security, it just opens up avenues for race conditions (which I guarantee will create more bugs down the line), and input lag for the normal player.
if inputState == true then
local AnimTrack = character.Humanoid.Animator:LoadAnimation("AnimationHere")
AnimTrack:Play()
elseif inputState == false then
AnimTrack:Stop()
Debounces["Movement Debounces"].Right = false
end
Lets use the above code as an example, if I play the animation track when the Input Begins; you are unable to reference AnimTrack in the InputEnd Function.
Now, lets say you load the AnimationTrack in each function;
if inputState == true then
local AnimTrack1 = character.Humanoid.Animator:LoadAnimation("AnimationHere")
AnimTrack1:Play()
elseif inputState == false then
local AnimTrack1,AnimTrack2 = character.Humanoid.Animator:LoadAnimation("AnimationHere"),character.Humanoid.Animator:LoadAnimation("AnimationHere")
AnimTrack1:Stop()
AnimTrack2:Play()
Debounces["Movement Debounces"].Right = false
end
Now you have an extra line of redundant code that is only needed for one line of code. Why not create a system that could hold these values that you could reference when needed and then they get removed?
You aren’t suppose to use animations like this, Animators have a cap on how many animations can be loaded at once (256).
Edit: The statement about the cap doesn’t actually make any sense now that I look into it, Animators cache the animation data so loading the same animation over and over won’t incur any memory issues or animation limit issues, so my question now is just why you’ve used a local variable, because you’re effectively doing something like this;
if value then
local mycomplicatedvalue = 123
doSomething(mycomplicatedvalue)
else
local mycomplicatedvalue = 123
doAnotherThing(mycomplicatedvalue)
end
And then saying that there’s no way around it, when you could just do this;
local mycomplicatedvalue = 123
if value then
doSomething(mycomplicatedvalue)
else
doAnotherThing(mycomplicatedvalue)
end
You *should* just be doing;
local MyAnim = Humanoid.Animator:LoadAnimation(script.Animation)
if InputState then -- the same as InputState == true
MyAnim:Play()
else
MyAnim:Stop()
end
Okay so, the connections animation table is meant to store the Instances of these animations being played. That’s why in the Client Animation Table; I add an instance to the Connection Animation table with the Animation Name being the header, and the actual Instance of the LoadAnimation being what the name connects to.
Connections["Animations"][AnimationInfo["Animation Name"]] = AnimTrack does this exact thing. The issue is; when I try to reference this Instance, it comes back nil. Which is impossible because the animation is playing before the function begins.
That’s my problem, I’m going to rework the animations entirely to be fully loaded on the client like you’ve recommended as I do agree; animations should be controlled by the client 98% of the time. However, my issue still occurs sadly.
When you read this, i’ll probably have redone my entire post to match the issue at hand once I go through and update the code a bit.
Also, if you want to know why I’m adding animation instances to the table;
I wanted their to be a way to add any Animation to a table that could be referenced by the entire script at any time. That way; I don’t have to create any extra variables above… the animation player will do that for me.
What was the error? I thought it was an “attempt to index nil with .KeyframeReached”, so I don’t understand how it’s a keyframe issue if the animation itself just doesn’t exist in the dictionary.
The issue was that the KeyframeReached is a very faulty system; it only works half the time… everything else was working perfectly fine; it was simply that the KeyframeReached isn’t fully operational. To fix it, I had to create a Heartbeat connection once the Animation was fired to wait for a certain amount of time, then fire and break the connection.