THE BUG
In a live Roblox session, the local-player Equip animation does not visually move the gun for the first ~600ms after Play. The animation track is playing correctly (TimePosition advances, weight is 1.0, marker signals fire on schedule), but motor.Transform on the Weapons Motor6D stays at CFrame.identity for that ~600ms window and then snaps directly to whatever pose corresponds to the current TimePosition, with no interpolation ramp. After the snap, the rest of the animation plays correctly.
In Roblox Studio the same animation works perfectly every time. In live, the very first equip after spawn also works (if it is done within about 4 seconds), and rapid re-equips within ~1 second works. After roughly 7 seconds of idle the failure is consistent every time.
SETUP
The rig uses a custom Motor6D called âWeaponsâ parented to the characterâs Torso. Part0 is the Torso. Part1 is set on tool.Equipped to the gunâs primary part, which is named âGripâ. The Equip animation has a âGripâ Pose channel densely keyframed from frame 0.
The tool itself uses RequiresHandle = false and has no engine-default RightGrip weld. The custom Weapons Motor6D is the only thing positioning the held gun. The gunâs primary part is unanchored.
PER-FRAME DATA
In live, on a failing equip:
t=0ms T=(0,0,0) tp=0.00 weight=0.00 Part1=Grip AssemblyRoot=HumanoidRootPart IdleWeight=0.00
t=100ms T=(0,0,0) tp=0.13 weight=1.00 Part1=Grip AssemblyRoot=HumanoidRootPart IdleWeight=1.00
t=300ms T=(0,0,0) tp=0.36 weight=1.00
t=600ms T=(0,0,0) tp=0.71 weight=1.00
t=650ms T=(0.82, -0.89, -0.63) tp=0.77 weight=1.00 â snap
t=950ms T=(0.62, -0.59, -0.94) tp=1.15 weight=1.00
In Studio, same animation, same code:
t=50ms T=(0.61, -0.84, 0.47) tp=0.10 weight=0.96 â keyframes apply from frame 0
t=100ms T=(0.61, -0.86, 0.53) tp=0.15 weight=1.00
The cold-start is time-based, not tp-based. The snap happens at roughly 600-650ms of wall clock regardless of where TimePosition is at that moment.
WHAT WAS RULED OUT
Motor6D.Part1 race or not-yet-set. Confirmed Part1 = Grip from t=0 in every sample.
Tool not yet a descendant of the character. Confirmed in-character from t=0.
Assembly not merged with the rig. AssemblyRootPart = HumanoidRootPart from t=0.
Anchored gun part. The primary part is unanchored.
Network ownership of the gunâs primary part stuck on the server. Tried calling primaryPart:SetNetworkOwner(player) right after motor.Part1 = primaryPart. No change.
AnimationTrack rebuilt per equip. Tried both fresh LoadAnimation every equip and caching the track for the lifetime of the character. Same bug both ways.
AnimationPriority masking. The Idle stance plays at Action priority alongside Equip; tried Equip at Action2, Action3, and Action4. All show the same identity output during the cold window. Idleâs pose also fails to reach the motor during that window even though Idle is at full weight, so itâs not just the Equip track thatâs silent - itâs the motor thatâs silent.
Asset not preloaded. ContentProvider:PreloadAsync is called over every Animation in the assets folder at startup.
Fade-in or weight ramp. Weight reaches 1.0 by t=100ms; identity output continues for another ~500ms after that.
Warmup at LoadAnimation. Tried calling track:Play(0, 0, 0) followed by task.wait() and track:Stop(0) right after LoadAnimation, before the user-facing Play. No change.
Note, all other animations other than equip seem to be working fine, I will test a new equipping animation but have not yet gotten the chance to make it.
WHAT IS SURPRISING
The Animator is processing the track per its own counters - TimePosition ticks normally, WeightCurrent reads 1.0, marker signals fire on schedule - but its output to motor.Transform is identity for the cold-start window. It looks like the per-Motor6D write path is gated by a separate lazy-init that takes ~600ms in live and is instant in Studio.
The snap at ~600ms is hard, with no smooth interpolation ramp from identity to the keyframe value at the current tp. The Animator isnât producing low-weight identity output during the early window - itâs not producing output to this motor at all, then suddenly is.
REPRO
A custom rig with a non-default Motor6D (Part0 a character part, Part1 named to match an animation Pose). A tool with RequiresHandle = false and a primary-part-only model. Set Part1 in the toolâs Equipped handler, then play an animation that drives that Pose. In Studio it animates from frame 0. In live, after a few seconds of idle, the motor stays at identity for ~600ms before the animation visually starts.
QUESTIONS
Is there an internal lazy-init of per-Motor6D animator state in live that is bypassed in Studio? Is there a supported way to warm up or pre-bind a Motor6D channel so the first Play after an idle period is not cold? More generally, what is the supported way to drive a custom (non-RightGrip) Motor6D from animations on a tool with RequiresHandle = false? Is this a game engine issue, I noticed there were animation issues recently, or did I make a mistake somewhere?