Try this, this will tell us how much frames there are in the sequence and also what frame it ended at
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local CutsceneAnimation = {}
CutsceneAnimation.__index = CutsceneAnimation
function CutsceneAnimation.new(sequence : KeyframeSequence)
local self = {}
setmetatable(self, CutsceneAnimation)
self.KeyframeSequence = sequence
self.Keyframes = sequence:GetKeyframes()
self.Frame = 1
self.Motors = {}
print(#self.Keyframes.. "keyframes")
return self
end
function CutsceneAnimation:UpdatePose(frame, DT : number)
for _, pose : Pose in ipairs(frame:GetDescendants()) do
if pose:IsA("Pose") then
local Motor : Motor6D = self.Motors[pose.Name]
if Motor then
local x,y,z = pose.CFrame:ToEulerAnglesXYZ()
if x == 0 and y == 0 and z == 0 and pose.CFrame.Position.Magnitude == 0 then
continue
end
Motor.Transform = Motor.Transform:Lerp(pose.CFrame, DT)
end
end
end
end
function CutsceneAnimation:Play(Rig : Model, startCFrame : CFrame)
local CutsceneRig = Rig
self.CutsceneRig = CutsceneRig
local accumulatedTime = self.AccumulatedTime or 0
for _, motor in ipairs(self.CutsceneRig:GetDescendants()) do
if motor:IsA("Motor6D") then
self.Motors[motor.Name] = motor
end
end
if not startCFrame then
startCFrame = CutsceneRig.PrimaryPart.CFrame
end
CutsceneRig.PrimaryPart.Anchored = true
CutsceneRig.PrimaryPart.CFrame = startCFrame
CutsceneAnimation[Rig] = true
table.sort(self.Keyframes, function(a, b)
return a.Time < b.Time
end)
self:UpdatePose(self.Keyframes[self.Frame], 0)
local Connection = nil
Connection = RunService.Heartbeat:Connect(function(DT)
if self.Paused then return end
accumulatedTime += DT
while self.Frame < #self.Keyframes and accumulatedTime >= self.Keyframes[self.Frame + 1].Time do
self.Frame += 1
self:UpdatePose(self.Keyframes[self.Frame], DT * 7)
end
if accumulatedTime >= self.Keyframes[self.EndKeyframe or #self.Keyframes].Time then
print("Stopped at"..self.Frame)
Connection:Disconnect()
Connection = nil
CutsceneAnimation[Rig] = false
end
end)
end
return CutsceneAnimation
Am I missing something? To me, it seems like the speed is the same, it just has maybe a slight playing delay at the beginning, which is probably due to the fact that animations has to replicate to other clients.
You can run the animation locally for every player and see if that helps.
Nothing was mentioned about the speed alone of the door. In the studio playback you can see it doesn’t fully go into the wall, but in the playtest it goes beyond the wall.
I wasn’t gonna give up on you that easily @kalet14 ,
Alright so get this awesome spring module and put it inside of ReplicatedStorage (I didn’t create) spr (Spring Module).rbxm (9.6 KB)
It’ll allow super smooth movement with some nice spring action, also it’s safe so dont worry about that
And then use this updated module
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local spr = require(ReplicatedStorage.spr)
local RunService = game:GetService("RunService")
local CutsceneAnimation = {}
CutsceneAnimation.__index = CutsceneAnimation
function CutsceneAnimation.new(sequence : KeyframeSequence)
local self = {}
setmetatable(self, CutsceneAnimation)
self.KeyframeSequence = sequence
self.Keyframes = sequence:GetKeyframes()
self.Frame = 1
self.Motors = {}
return self
end
function CutsceneAnimation:Play(Rig : Model, startCFrame : CFrame)
local CutsceneRig = Rig
self.CutsceneRig = CutsceneRig
local accumulatedTime = self.AccumulatedTime or 0
for _, motor in ipairs(self.CutsceneRig:GetDescendants()) do
if motor:IsA("Motor6D") then
self.Motors[motor.Name] = motor
end
end
print(self.Motors)
if not startCFrame then
startCFrame = CutsceneRig.PrimaryPart.CFrame
end
CutsceneRig.PrimaryPart.Anchored = true
CutsceneRig.PrimaryPart.CFrame = startCFrame
CutsceneAnimation[Rig] = true
table.sort(self.Keyframes, function(a, b)
return a.Time < b.Time
end)
local Connection = nil
local function updatePose()
for _, pose : Pose in ipairs(self.Keyframes[self.Frame]:GetDescendants()) do
if pose:IsA("Pose") then
local Motor : Motor6D = self.Motors[pose.Name]
if Motor then
local x,y,z = pose.CFrame:ToEulerAnglesXYZ()
if x == 0 and y == 0 and z == 0 and pose.CFrame.Position.Magnitude == 0 then
continue
end
spr.target(Motor, .4, 1,{
Transform = pose.CFrame
})
end
end
end
end
Connection = RunService.Heartbeat:Connect(function(DT)
if self.Paused then return end
accumulatedTime += DT
while self.Frame < #self.Keyframes and accumulatedTime >= self.Keyframes[self.Frame + 1].Time do
self.Frame += 1
updatePose()
end
if accumulatedTime >= self.Keyframes[self.EndKeyframe or #self.Keyframes].Time then
print("Animation ended")
Connection:Disconnect()
Connection = nil
CutsceneAnimation[Rig] = false
end
end)
end
return CutsceneAnimation
Unfortunately, I found a solution that isn’t really that well and limits my animating abilities for any future animations I make with the door model and that is using the animation editor that Studio has built in and I had to make a ton of keyframes since using any sort of easing at all will break the doors animation.
I haven’t tried it, so I’m not really sure how it’ll turn out but I’ve heard of the spring module in two of my previous posts I’ve made and this time I might consider using it for the other door models I’m making which I won’t be able to animate with the default animator due to the doors needing some sort of bounce to them to make the animation actually look good.
Nah im not giving up trust @kalet14,take a screenshot of your door and let me see all the Motor6Ds it has inside, I TOLD YOU I WOULD NOT GIVE UP ON YOU