Before I say any more, this method does NOT work. However, if Roblox were to ever release a similar feature or set-up to ‘RegisterKeyframeSequence’ this might just be possible!! The idea was to send the Client a KeyframeSequence and having it be safe so the id cannot be taken, because its fake (lol)!
So heres my idea on how it works:
- The Client asks the Server for a specific KeyframeSequence (through a RemoteFunction)
- The Server takes that request, finds the KeyframeSequence, and then converts it into a table
- The table is returned to the Client and builds back the KeyframeSequnce using Instance.new() to recreate the KeyframeSequence, I’m not 100% sure on this part, but since the instances’ parent was not given it become invisible, sort of. (If I’m wrong please correct me.)
- The KeyframeSequence is turned into a hash id (or a false animation id that cannot be stolen) and the Client clears the KeyframeSequence so it cannot be used or manipulated, however I was thinking of adding a way for the server to save the table so the RemoteFunction wouldn’t take forever to respond, etc.
- Finally, the Client plays a safe animation that exploiters cannot go and get because its just a hash id. Unfortunately this is the part where it won’t work, because its only available in studio. Sorry.
Heres how you can recreate it:
Use this setup:
In the server script, use this:
ReplicatedStorage = game:GetService("ReplicatedStorage")
local SavedKeyframeSequences = {}
function ConvertKeyframeSequenceToTable(KeyframeSequence)
local KFS_T = {}
for i, Keyframe in pairs(KeyframeSequence:GetChildren()) do
local Poses = {}
for i, Pose in pairs(Keyframe:GetDescendants()) do
table.insert(Poses, {
Name = Pose.Name;
CFrameNew = Pose.CFrame;
EasingDirection = Pose.EasingDirection;
EasingStyle = Pose.EasingStyle;
Weight = Pose.Weight;
})
end
table.insert(KFS_T, {
BaseName = Keyframe.Name;
BaseTime = Keyframe.Time;
KeyframePoses = Poses;
})
pcall(function()
Poses = nil
end)
end
SavedKeyframeSequences[KeyframeSequence.Name] = KFS_T
return KFS_T, pcall(function()
KFS_T = nil
end)
end
ReplicatedStorage.Emotes.OnServerInvoke = function(ClientPlayer)
return ConvertKeyframeSequenceToTable(script.KeyframeSequence)
end
In the local script, use this:
task.wait(3)
local function CreateKeyframeSequence(Table)
local KeyframeSequence = Instance.new("KeyframeSequence")
KeyframeSequence.Parent = script
for i = 1, #Table do
local Keyframe = Instance.new("Keyframe")
Keyframe.Name = Table[i].BaseName
Keyframe.Time = Table[i].BaseTime
Keyframe.Parent = KeyframeSequence
for i2 = 1, #Table[i].KeyframePoses do
local Pose = Instance.new("Pose")
Pose.Name = Table[i].KeyframePoses[i2].Name
Pose.CFrame = Table[i].KeyframePoses[i2].CFrameNew
Pose.EasingDirection = Table[i].KeyframePoses[i2].EasingDirection
Pose.EasingStyle = Table[i].KeyframePoses[i2].EasingStyle
Pose.Weight = Table[i].KeyframePoses[i2].Weight
Pose.Parent = Keyframe
end
Keyframe.LowerTorso.Parent = Keyframe.HumanoidRootPart
Keyframe.LeftUpperLeg.Parent = Keyframe.HumanoidRootPart.LowerTorso
Keyframe.LeftLowerLeg.Parent = Keyframe.HumanoidRootPart.LowerTorso.LeftUpperLeg
Keyframe.LeftFoot.Parent = Keyframe.HumanoidRootPart.LowerTorso.LeftUpperLeg.LeftLowerLeg
Keyframe.RightUpperLeg.Parent = Keyframe.HumanoidRootPart.LowerTorso
Keyframe.RightLowerLeg.Parent = Keyframe.HumanoidRootPart.LowerTorso.RightUpperLeg
Keyframe.RightFoot.Parent = Keyframe.HumanoidRootPart.LowerTorso.RightUpperLeg.RightLowerLeg
Keyframe.UpperTorso.Parent = Keyframe.HumanoidRootPart.LowerTorso
Keyframe.Head.Parent = Keyframe.HumanoidRootPart.LowerTorso.UpperTorso
Keyframe.LeftUpperArm.Parent = Keyframe.HumanoidRootPart.LowerTorso.UpperTorso
Keyframe.LeftLowerArm.Parent = Keyframe.HumanoidRootPart.LowerTorso.UpperTorso.LeftUpperArm
Keyframe.LeftHand.Parent = Keyframe.HumanoidRootPart.LowerTorso.UpperTorso.LeftUpperArm.LeftLowerArm
Keyframe.RightUpperArm.Parent = Keyframe.HumanoidRootPart.LowerTorso.UpperTorso
Keyframe.RightLowerArm.Parent = Keyframe.HumanoidRootPart.LowerTorso.UpperTorso.RightUpperArm
Keyframe.RightHand.Parent = Keyframe.HumanoidRootPart.LowerTorso.UpperTorso.RightUpperArm.RightLowerArm
end
return KeyframeSequence
end
local ActualKeyframeSequence = CreateKeyframeSequence(game:GetService("ReplicatedStorage").Emotes:InvokeServer())
local Humanoid = game.Players.LocalPlayer.Character.Humanoid
local KeyframeSequenceProvider = game:GetService("KeyframeSequenceProvider")
local Animation = Instance.new("Animation")
Animation.AnimationId = KeyframeSequenceProvider:RegisterKeyframeSequence(ActualKeyframeSequence)
local Emote = Humanoid:LoadAnimation(Animation)
Emote:Play()
I was going to use it for my emote game, but its practically worthless at the moment lol. If any of you know a better method or a way to make my idea better, etc; please let me know! I’m more than open to any of your ideas.