The sitting animation will not play on the players screen, but will on the server view.
This is the weirdest issue I’ve encountered every while developing. Im using the animate script from this model made by roblox:
https://www.roblox.com/library/187789986/Drooling-Zombie
The NPC is an R6 rig inserted using the rig builder plugin that comes with studio.
Screenshots of the issue
Client View (ALSO LOOKS LIKE THIS WHEN PLAYING THE GAME NORMALLY)
Server View:
The npc with the animate script:
NPC_With_Unusual_Sitting_Animation.rbxm (13.4 KB)
Animate Script:
function waitForChild(parent, childName)
local child = parent:findFirstChild(childName)
if child then return child end
while true do
child = parent.ChildAdded:wait()
if child.Name==childName then return child end
end
end
local Figure = script.Parent
local Torso = waitForChild(Figure, "Torso")
local RightShoulder = waitForChild(Torso, "Right Shoulder")
local LeftShoulder = waitForChild(Torso, "Left Shoulder")
local RightHip = waitForChild(Torso, "Right Hip")
local LeftHip = waitForChild(Torso, "Left Hip")
local Neck = waitForChild(Torso, "Neck")
local Humanoid = waitForChild(Figure, "Humanoid")
local pose = "Standing"
local currentAnim = ""
local currentAnimTrack = nil
local currentAnimKeyframeHandler = nil
local currentAnimSpeed = 1.0
local animTable = {}
local animNames = {
idle = {
{ id = "http://www.roblox.com/asset/?id=125750544", weight = 9 },
{ id = "http://www.roblox.com/asset/?id=125750618", weight = 1 }
},
walk = {
{ id = "http://www.roblox.com/asset/?id=125749145", weight = 10 }
},
run = {
{ id = "run.xml", weight = 10 }
},
jump = {
{ id = "http://www.roblox.com/asset/?id=125750702", weight = 10 }
},
fall = {
{ id = "http://www.roblox.com/asset/?id=125750759", weight = 10 }
},
climb = {
{ id = "http://www.roblox.com/asset/?id=125750800", weight = 10 }
},
toolnone = {
{ id = "http://www.roblox.com/asset/?id=125750867", weight = 10 }
},
toolslash = {
{ id = "http://www.roblox.com/asset/?id=129967390", weight = 10 }
-- { id = "slash.xml", weight = 10 }
},
toollunge = {
{ id = "http://www.roblox.com/asset/?id=129967478", weight = 10 }
},
wave = {
{ id = "http://www.roblox.com/asset/?id=128777973", weight = 10 }
},
point = {
{ id = "http://www.roblox.com/asset/?id=128853357", weight = 10 }
},
dance = {
{ id = "http://www.roblox.com/asset/?id=130018893", weight = 10 },
{ id = "http://www.roblox.com/asset/?id=132546839", weight = 10 },
{ id = "http://www.roblox.com/asset/?id=132546884", weight = 10 }
},
dance2 = {
{ id = "http://www.roblox.com/asset/?id=160934142", weight = 10 },
{ id = "http://www.roblox.com/asset/?id=160934298", weight = 10 },
{ id = "http://www.roblox.com/asset/?id=160934376", weight = 10 }
},
dance3 = {
{ id = "http://www.roblox.com/asset/?id=160934458", weight = 10 },
{ id = "http://www.roblox.com/asset/?id=160934530", weight = 10 },
{ id = "http://www.roblox.com/asset/?id=160934593", weight = 10 }
},
laugh = {
{ id = "http://www.roblox.com/asset/?id=129423131", weight = 10 }
},
cheer = {
{ id = "http://www.roblox.com/asset/?id=129423030", weight = 10 }
},
}
-- Existance in this list signifies that it is an emote, the value indicates if it is a looping emote
local emoteNames = { wave = false, point = false, dance = true, dance2 = true, dance3 = true, laugh = false, cheer = false}
math.randomseed(tick())
function configureAnimationSet(name, fileList)
if (animTable[name] ~= nil) then
for _, connection in pairs(animTable[name].connections) do
connection:disconnect()
end
end
animTable[name] = {}
animTable[name].count = 0
animTable[name].totalWeight = 0
animTable[name].connections = {}
-- check for config values
local config = script:FindFirstChild(name)
if (config ~= nil) then
-- print("Loading anims " .. name)
table.insert(animTable[name].connections, config.ChildAdded:connect(function(child) configureAnimationSet(name, fileList) end))
table.insert(animTable[name].connections, config.ChildRemoved:connect(function(child) configureAnimationSet(name, fileList) end))
local idx = 1
for _, childPart in pairs(config:GetChildren()) do
if (childPart:IsA("Animation")) then
table.insert(animTable[name].connections, childPart.Changed:connect(function(property) configureAnimationSet(name, fileList) end))
animTable[name][idx] = {}
animTable[name][idx].anim = childPart
local weightObject = childPart:FindFirstChild("Weight")
if (weightObject == nil) then
animTable[name][idx].weight = 1
else
animTable[name][idx].weight = weightObject.Value
end
animTable[name].count = animTable[name].count + 1
animTable[name].totalWeight = animTable[name].totalWeight + animTable[name][idx].weight
-- print(name .. " [" .. idx .. "] " .. animTable[name][idx].anim.AnimationId .. " (" .. animTable[name][idx].weight .. ")")
idx = idx + 1
end
end
end
-- fallback to defaults
if (animTable[name].count <= 0) then
for idx, anim in pairs(fileList) do
animTable[name][idx] = {}
animTable[name][idx].anim = Instance.new("Animation")
animTable[name][idx].anim.Name = name
animTable[name][idx].anim.AnimationId = anim.id
animTable[name][idx].weight = anim.weight
animTable[name].count = animTable[name].count + 1
animTable[name].totalWeight = animTable[name].totalWeight + anim.weight
-- print(name .. " [" .. idx .. "] " .. anim.id .. " (" .. anim.weight .. ")")
end
end
end
-- Setup animation objects
function scriptChildModified(child)
local fileList = animNames[child.Name]
if (fileList ~= nil) then
configureAnimationSet(child.Name, fileList)
end
end
script.ChildAdded:connect(scriptChildModified)
script.ChildRemoved:connect(scriptChildModified)
for name, fileList in pairs(animNames) do
configureAnimationSet(name, fileList)
end
-- ANIMATION
-- declarations
local toolAnim = "None"
local toolAnimTime = 0
local jumpAnimTime = 0
local jumpAnimDuration = 0.3
local toolTransitionTime = 0.1
local fallTransitionTime = 0.3
local jumpMaxLimbVelocity = 0.75
-- functions
function stopAllAnimations()
local oldAnim = currentAnim
-- return to idle if finishing an emote
if (emoteNames[oldAnim] ~= nil and emoteNames[oldAnim] == false) then
oldAnim = "idle"
end
currentAnim = ""
if (currentAnimKeyframeHandler ~= nil) then
currentAnimKeyframeHandler:disconnect()
end
if (currentAnimTrack ~= nil) then
currentAnimTrack:Stop()
currentAnimTrack:Destroy()
currentAnimTrack = nil
end
return oldAnim
end
function setAnimationSpeed(speed)
if speed ~= currentAnimSpeed then
currentAnimSpeed = speed
currentAnimTrack:AdjustSpeed(currentAnimSpeed)
end
end
function keyFrameReachedFunc(frameName)
if (frameName == "End") then
-- print("Keyframe : ".. frameName)
local repeatAnim = stopAllAnimations()
local animSpeed = currentAnimSpeed
playAnimation(repeatAnim, 0.0, Humanoid)
setAnimationSpeed(animSpeed)
end
end
-- Preload animations
function playAnimation(animName, transitionTime, humanoid)
local idleFromEmote = (animName == "idle" and emoteNames[currentAnim] ~= nil)
if (animName ~= currentAnim and not idleFromEmote) then
if (currentAnimTrack ~= nil) then
currentAnimTrack:Stop(transitionTime)
currentAnimTrack:Destroy()
end
currentAnimSpeed = 1.0
local roll = math.random(1, animTable[animName].totalWeight)
local origRoll = roll
local idx = 1
while (roll > animTable[animName][idx].weight) do
roll = roll - animTable[animName][idx].weight
idx = idx + 1
end
-- print(animName .. " " .. idx .. " [" .. origRoll .. "]")
local anim = animTable[animName][idx].anim
-- load it to the humanoid; get AnimationTrack
currentAnimTrack = humanoid:LoadAnimation(anim)
-- play the animation
currentAnimTrack:Play(transitionTime)
currentAnim = animName
-- set up keyframe name triggers
if (currentAnimKeyframeHandler ~= nil) then
currentAnimKeyframeHandler:disconnect()
end
currentAnimKeyframeHandler = currentAnimTrack.KeyframeReached:connect(keyFrameReachedFunc)
end
end
-------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------
local toolAnimName = ""
local toolAnimTrack = nil
local currentToolAnimKeyframeHandler = nil
function toolKeyFrameReachedFunc(frameName)
if (frameName == "End") then
-- print("Keyframe : ".. frameName)
local repeatAnim = stopToolAnimations()
playToolAnimation(repeatAnim, 0.0, Humanoid)
end
end
function playToolAnimation(animName, transitionTime, humanoid)
if (animName ~= toolAnimName) then
if (toolAnimTrack ~= nil) then
toolAnimTrack:Stop()
toolAnimTrack:Destroy()
transitionTime = 0
end
local roll = math.random(1, animTable[animName].totalWeight)
local origRoll = roll
local idx = 1
while (roll > animTable[animName][idx].weight) do
roll = roll - animTable[animName][idx].weight
idx = idx + 1
end
-- print(animName .. " * " .. idx .. " [" .. origRoll .. "]")
local anim = animTable[animName][idx].anim
-- load it to the humanoid; get AnimationTrack
toolAnimTrack = humanoid:LoadAnimation(anim)
-- play the animation
toolAnimTrack:Play(transitionTime)
toolAnimName = animName
currentToolAnimKeyframeHandler = toolAnimTrack.KeyframeReached:connect(toolKeyFrameReachedFunc)
end
end
function stopToolAnimations()
local oldAnim = toolAnimName
if (currentToolAnimKeyframeHandler ~= nil) then
currentToolAnimKeyframeHandler:disconnect()
end
toolAnimName = ""
if (toolAnimTrack ~= nil) then
toolAnimTrack:Stop()
toolAnimTrack:Destroy()
toolAnimTrack = nil
end
return oldAnim
end
-------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------
function onRunning(speed)
if speed>0.01 then
playAnimation("walk", 0.1, Humanoid)
pose = "Running"
else
playAnimation("idle", 0.1, Humanoid)
pose = "Standing"
end
end
function onDied()
pose = "Dead"
end
function onJumping()
playAnimation("jump", 0.1, Humanoid)
jumpAnimTime = jumpAnimDuration
pose = "Jumping"
end
function onClimbing(speed)
playAnimation("climb", 0.1, Humanoid)
setAnimationSpeed(speed / 12.0)
pose = "Climbing"
end
function onGettingUp()
pose = "GettingUp"
end
function onFreeFall()
if (jumpAnimTime <= 0) then
playAnimation("fall", fallTransitionTime, Humanoid)
end
pose = "FreeFall"
end
function onFallingDown()
pose = "FallingDown"
end
function onSeated()
pose = "Seated"
end
function onPlatformStanding()
pose = "PlatformStanding"
end
function onSwimming(speed)
if speed>0 then
pose = "Running"
else
pose = "Standing"
end
end
function getTool()
for _, kid in ipairs(Figure:GetChildren()) do
if kid.className == "Tool" then return kid end
end
return nil
end
function getToolAnim(tool)
for _, c in ipairs(tool:GetChildren()) do
if c.Name == "toolanim" and c.className == "StringValue" then
return c
end
end
return nil
end
function animateTool()
if (toolAnim == "None") then
playToolAnimation("toolnone", toolTransitionTime, Humanoid)
return
end
if (toolAnim == "Slash") then
playToolAnimation("toolslash", 0, Humanoid)
return
end
if (toolAnim == "Lunge") then
playToolAnimation("toollunge", 0, Humanoid)
return
end
end
function moveSit()
RightShoulder.MaxVelocity = 0.15
LeftShoulder.MaxVelocity = 0.15
RightShoulder:SetDesiredAngle(3.14 /2)
LeftShoulder:SetDesiredAngle(-3.14 /2)
RightHip:SetDesiredAngle(3.14 /2)
LeftHip:SetDesiredAngle(-3.14 /2)
end
local lastTick = 0
function move(time)
local amplitude = 1
local frequency = 1
local deltaTime = time - lastTick
lastTick = time
local climbFudge = 0
local setAngles = false
if (jumpAnimTime > 0) then
jumpAnimTime = jumpAnimTime - deltaTime
end
if (pose == "FreeFall" and jumpAnimTime <= 0) then
playAnimation("fall", fallTransitionTime, Humanoid)
elseif (pose == "Seated") then
stopAllAnimations()
moveSit()
return
elseif (pose == "Running") then
playAnimation("walk", 0.1, Humanoid)
elseif (pose == "Dead" or pose == "GettingUp" or pose == "FallingDown" or pose == "Seated" or pose == "PlatformStanding") then
-- print("Wha " .. pose)
amplitude = 0.1
frequency = 1
setAngles = true
end
if (setAngles) then
desiredAngle = amplitude * math.sin(time * frequency)
RightShoulder:SetDesiredAngle(desiredAngle + climbFudge)
LeftShoulder:SetDesiredAngle(desiredAngle - climbFudge)
RightHip:SetDesiredAngle(-desiredAngle)
LeftHip:SetDesiredAngle(-desiredAngle)
end
-- Tool Animation handling
local tool = getTool()
if tool then
animStringValueObject = getToolAnim(tool)
if animStringValueObject then
toolAnim = animStringValueObject.Value
-- message recieved, delete StringValue
animStringValueObject.Parent = nil
toolAnimTime = time + .3
end
if time > toolAnimTime then
toolAnimTime = 0
toolAnim = "None"
end
animateTool()
else
stopToolAnimations()
toolAnim = "None"
toolAnimTime = 0
end
end
-- connect events
Humanoid.Died:connect(onDied)
Humanoid.Running:connect(onRunning)
Humanoid.Jumping:connect(onJumping)
Humanoid.Climbing:connect(onClimbing)
Humanoid.GettingUp:connect(onGettingUp)
Humanoid.FreeFalling:connect(onFreeFall)
Humanoid.FallingDown:connect(onFallingDown)
Humanoid.Seated:connect(onSeated)
Humanoid.PlatformStanding:connect(onPlatformStanding)
Humanoid.Swimming:connect(onSwimming)
-- main program
local runService = game:service("RunService");
-- initialize to idle
playAnimation("idle", 0.1, Humanoid)
pose = "Standing"
while Figure.Parent~=nil do
local _, time = wait(0.1)
move(time)
end
Code to make the NPC sit down:
HumanoidRootPart.CFrame = Seat.CFrame
Seat.Disabled = false
Seat:Sit(humanoid)
NPC.Parent = workspace.Map.SeatedNPCs