Starter Player Animation not working

Hello! My name is RainbowStachio, and recently I created a character mesh, that I wanted to make into a roblox character. I followed many tutorials about it, and I managed to get to the point where my character was able to be inside the game:


^^^ Here you see my character (the yellow figure) standing. There are no animations playing, its just this single still pose. ^^^


^^^ Here you see the skeleton of the model, and the higherarchy on the right. As you can see, I have an animate script which I copied from my player character as I was in-game. The Blue circles are where the Humanoid Root Part is. An important thing to know is that the humanoid is set to R15 and the game settings are set to R15. ^^^

The Animate Script (It looks a little weird because of the indentations thing)
local Character = script.Parent

local Humanoid = Character:WaitForChild(“Humanoid”)
local pose = “Standing”

local userNoUpdateOnLoopSuccess, userNoUpdateOnLoopValue = pcall(function() return UserSettings():IsUserFeatureEnabled(“UserNoUpdateOnLoop”) end)
local userNoUpdateOnLoop = userNoUpdateOnLoopSuccess and userNoUpdateOnLoopValue

local animateScriptEmoteHookFlagExists, animateScriptEmoteHookFlagEnabled = pcall(function()
return UserSettings():IsUserFeatureEnabled(“UserAnimateScriptEmoteHook”)
end)
local FFlagAnimateScriptEmoteHook = animateScriptEmoteHookFlagExists and animateScriptEmoteHookFlagEnabled

local AnimationSpeedDampeningObject = script:FindFirstChild(“ScaleDampeningPercent”)
local HumanoidHipHeight = 2

local EMOTE_TRANSITION_TIME = 0.1

local currentAnim = “”
local currentAnimInstance = nil
local currentAnimTrack = nil
local currentAnimKeyframeHandler = nil
local currentAnimSpeed = 1.0

local runAnimTrack = nil
local runAnimKeyframeHandler = nil

local PreloadedAnims = {}

local animTable = {}
local animNames = {
idle = {
{ id = “http://www.roblox.com/asset/?id=507766666”, weight = 1 },
{ id = “http://www.roblox.com/asset/?id=507766951”, weight = 1 },
{ id = “http://www.roblox.com/asset/?id=507766388”, weight = 9 }
},
walk = {
{ id = “http://www.roblox.com/asset/?id=507777826”, weight = 10 }
},
run = {
{ id = “http://www.roblox.com/asset/?id=507767714”, weight = 10 }
},
swim = {
{ id = “http://www.roblox.com/asset/?id=507784897”, weight = 10 }
},
swimidle = {
{ id = “http://www.roblox.com/asset/?id=507785072”, weight = 10 }
},
jump = {
{ id = “http://www.roblox.com/asset/?id=507765000”, weight = 10 }
},
fall = {
{ id = “http://www.roblox.com/asset/?id=507767968”, weight = 10 }
},
climb = {
{ id = “http://www.roblox.com/asset/?id=507765644”, weight = 10 }
},
sit = {
{ id = “http://www.roblox.com/asset/?id=2506281703”, weight = 10 }
},
toolnone = {
{ id = “http://www.roblox.com/asset/?id=507768375”, weight = 10 }
},
toolslash = {
{ id = “http://www.roblox.com/asset/?id=522635514”, weight = 10 }
},
toollunge = {
{ id = “http://www.roblox.com/asset/?id=522638767”, weight = 10 }
},
wave = {
{ id = “http://www.roblox.com/asset/?id=507770239”, weight = 10 }
},
point = {
{ id = “http://www.roblox.com/asset/?id=507770453”, weight = 10 }
},
dance = {
{ id = “http://www.roblox.com/asset/?id=507771019”, weight = 10 },
{ id = “http://www.roblox.com/asset/?id=507771955”, weight = 10 },
{ id = “http://www.roblox.com/asset/?id=507772104”, weight = 10 }
},
dance2 = {
{ id = “http://www.roblox.com/asset/?id=507776043”, weight = 10 },
{ id = “http://www.roblox.com/asset/?id=507776720”, weight = 10 },
{ id = “http://www.roblox.com/asset/?id=507776879”, weight = 10 }
},
dance3 = {
{ id = “http://www.roblox.com/asset/?id=507777268”, weight = 10 },
{ id = “http://www.roblox.com/asset/?id=507777451”, weight = 10 },
{ id = “http://www.roblox.com/asset/?id=507777623”, weight = 10 }
},
laugh = {
{ id = “http://www.roblox.com/asset/?id=507770818”, weight = 10 }
},
cheer = {
{ id = “http://www.roblox.com/asset/?id=507770677”, 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 findExistingAnimationInSet(set, anim)
if set == nil or anim == nil then
return 0
end

for idx = 1, set.count, 1 do 
	if set[idx].anim.AnimationId == anim.AnimationId then
		return idx
	end
end

return 0

end

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 = {}

local allowCustomAnimations = true

local success, msg = pcall(function() allowCustomAnimations = game:GetService("StarterPlayer").AllowCustomAnimations end)
if not success then
	allowCustomAnimations = true
end

-- check for config values
local config = script:FindFirstChild(name)
if (allowCustomAnimations and config ~= nil) then
	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 = 0
	for _, childPart in pairs(config:GetChildren()) do
		if (childPart:IsA("Animation")) then
			local newWeight = 1
			local weightObject = childPart:FindFirstChild("Weight")
			if (weightObject ~= nil) then
				newWeight = weightObject.Value
			end
			animTable[name].count = animTable[name].count + 1
			idx = animTable[name].count
			animTable[name][idx] = {}
			animTable[name][idx].anim = childPart
			animTable[name][idx].weight = newWeight
			animTable[name].totalWeight = animTable[name].totalWeight + animTable[name][idx].weight
			table.insert(animTable[name].connections, childPart.Changed:connect(function(property) configureAnimationSet(name, fileList) end))
			table.insert(animTable[name].connections, childPart.ChildAdded:connect(function(property) configureAnimationSet(name, fileList) end))
			table.insert(animTable[name].connections, childPart.ChildRemoved:connect(function(property) configureAnimationSet(name, fileList) end))
		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
	end
end

-- preload anims
for i, animType in pairs(animTable) do
	for idx = 1, animType.count, 1 do
		if PreloadedAnims[animType[idx].anim.AnimationId] == nil then
			Humanoid:LoadAnimation(animType[idx].anim)
			PreloadedAnims[animType[idx].anim.AnimationId] = true
		end				
	end
end

end


function configureAnimationSetOld(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 = {}

local allowCustomAnimations = true

local success, msg = pcall(function() allowCustomAnimations = game:GetService("StarterPlayer").AllowCustomAnimations end)
if not success then
	allowCustomAnimations = true
end

-- check for config values
local config = script:FindFirstChild(name)
if (allowCustomAnimations and config ~= nil) then
	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
			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

-- preload anims
for i, animType in pairs(animTable) do
	for idx = 1, animType.count, 1 do 
		Humanoid:LoadAnimation(animType[idx].anim)
	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.31

local toolTransitionTime = 0.1
local fallTransitionTime = 0.2

local currentlyPlayingEmote = false

– 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

if FFlagAnimateScriptEmoteHook and currentlyPlayingEmote then
	oldAnim = "idle"
	currentlyPlayingEmote = false
end

currentAnim = ""
currentAnimInstance = nil
if (currentAnimKeyframeHandler ~= nil) then
	currentAnimKeyframeHandler:disconnect()
end

if (currentAnimTrack ~= nil) then
	currentAnimTrack:Stop()
	currentAnimTrack:Destroy()
	currentAnimTrack = nil
end

-- clean up walk if there is one
if (runAnimKeyframeHandler ~= nil) then
	runAnimKeyframeHandler:disconnect()
end

if (runAnimTrack ~= nil) then
	runAnimTrack:Stop()
	runAnimTrack:Destroy()
	runAnimTrack = nil
end

return oldAnim

end

function getHeightScale()
if Humanoid then
if not Humanoid.AutomaticScalingEnabled then
return 1
end

	local scale = Humanoid.HipHeight / HumanoidHipHeight
	if AnimationSpeedDampeningObject == nil then
		AnimationSpeedDampeningObject = script:FindFirstChild("ScaleDampeningPercent")
	end
	if AnimationSpeedDampeningObject ~= nil then
		scale = 1 + (Humanoid.HipHeight - HumanoidHipHeight) * AnimationSpeedDampeningObject.Value / HumanoidHipHeight
	end
	return scale
end	
return 1

end

local smallButNotZero = 0.0001
function setRunSpeed(speed)
local speedScaled = speed * 1.25
local heightScale = getHeightScale()
local runSpeed = speedScaled / heightScale

if runSpeed ~= currentAnimSpeed then
	if runSpeed < 0.33 then
		currentAnimTrack:AdjustWeight(1.0)		
		runAnimTrack:AdjustWeight(smallButNotZero)
	elseif runSpeed < 0.66 then
		local weight = ((runSpeed - 0.33) / 0.33)
		currentAnimTrack:AdjustWeight(1.0 - weight + smallButNotZero)
		runAnimTrack:AdjustWeight(weight + smallButNotZero)
	else
		currentAnimTrack:AdjustWeight(smallButNotZero)
		runAnimTrack:AdjustWeight(1.0)
	end
	currentAnimSpeed = runSpeed
	runAnimTrack:AdjustSpeed(runSpeed)
	currentAnimTrack:AdjustSpeed(runSpeed)
end	

end

function setAnimationSpeed(speed)
if currentAnim == “walk” then
setRunSpeed(speed)
else
if speed ~= currentAnimSpeed then
currentAnimSpeed = speed
currentAnimTrack:AdjustSpeed(currentAnimSpeed)
end
end
end

function keyFrameReachedFunc(frameName)
if (frameName == “End”) then
if currentAnim == “walk” then
if userNoUpdateOnLoop == true then
if runAnimTrack.Looped ~= true then
runAnimTrack.TimePosition = 0.0
end
if currentAnimTrack.Looped ~= true then
currentAnimTrack.TimePosition = 0.0
end
else
runAnimTrack.TimePosition = 0.0
currentAnimTrack.TimePosition = 0.0
end
else
local repeatAnim = currentAnim
– return to idle if finishing an emote
if (emoteNames[repeatAnim] ~= nil and emoteNames[repeatAnim] == false) then
repeatAnim = “idle”
end

		if FFlagAnimateScriptEmoteHook and currentlyPlayingEmote then
			if currentAnimTrack.Looped then
				-- Allow the emote to loop
				return
			end
			
			repeatAnim = "idle"
			currentlyPlayingEmote = false
		end
		
		local animSpeed = currentAnimSpeed
		playAnimation(repeatAnim, 0.15, Humanoid)
		setAnimationSpeed(animSpeed)
	end
end

end

function rollAnimation(animName)
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
return idx
end

local function switchToAnim(anim, animName, transitionTime, humanoid)
– switch animation
if (anim ~= currentAnimInstance) then

	if (currentAnimTrack ~= nil) then
		currentAnimTrack:Stop(transitionTime)
		currentAnimTrack:Destroy()
	end

	if (runAnimTrack ~= nil) then
		runAnimTrack:Stop(transitionTime)
		runAnimTrack:Destroy()
		if userNoUpdateOnLoop == true then
			runAnimTrack = nil
		end
	end

	currentAnimSpeed = 1.0

	-- load it to the humanoid; get AnimationTrack
	currentAnimTrack = humanoid:LoadAnimation(anim)
	currentAnimTrack.Priority = Enum.AnimationPriority.Core
	 
	-- play the animation
	currentAnimTrack:Play(transitionTime)
	currentAnim = animName
	currentAnimInstance = anim

	-- set up keyframe name triggers
	if (currentAnimKeyframeHandler ~= nil) then
		currentAnimKeyframeHandler:disconnect()
	end
	currentAnimKeyframeHandler = currentAnimTrack.KeyframeReached:connect(keyFrameReachedFunc)
	
	-- check to see if we need to blend a walk/run animation
	if animName == "walk" then
		local runAnimName = "run"
		local runIdx = rollAnimation(runAnimName)

		runAnimTrack = humanoid:LoadAnimation(animTable[runAnimName][runIdx].anim)
		runAnimTrack.Priority = Enum.AnimationPriority.Core
		runAnimTrack:Play(transitionTime)		
		
		if (runAnimKeyframeHandler ~= nil) then
			runAnimKeyframeHandler:disconnect()
		end
		runAnimKeyframeHandler = runAnimTrack.KeyframeReached:connect(keyFrameReachedFunc)	
	end
end

end

function playAnimation(animName, transitionTime, humanoid)
local idx = rollAnimation(animName)
local anim = animTable[animName][idx].anim

switchToAnim(anim, animName, transitionTime, humanoid)
currentlyPlayingEmote = false

end

function playEmote(emoteAnim, transitionTime, humanoid)
switchToAnim(emoteAnim, emoteAnim.Name, transitionTime, humanoid)
currentlyPlayingEmote = true
end



local toolAnimName = “”
local toolAnimTrack = nil
local toolAnimInstance = nil
local currentToolAnimKeyframeHandler = nil

function toolKeyFrameReachedFunc(frameName)
if (frameName == “End”) then
playToolAnimation(toolAnimName, 0.0, Humanoid)
end
end

function playToolAnimation(animName, transitionTime, humanoid, priority)
local idx = rollAnimation(animName)
local anim = animTable[animName][idx].anim

	if (toolAnimInstance ~= anim) then
		
		if (toolAnimTrack ~= nil) then
			toolAnimTrack:Stop()
			toolAnimTrack:Destroy()
			transitionTime = 0
		end
				
		-- load it to the humanoid; get AnimationTrack
		toolAnimTrack = humanoid:LoadAnimation(anim)
		if priority then
			toolAnimTrack.Priority = priority
		end
		 
		-- play the animation
		toolAnimTrack:Play(transitionTime)
		toolAnimName = animName
		toolAnimInstance = anim

		currentToolAnimKeyframeHandler = toolAnimTrack.KeyframeReached:connect(toolKeyFrameReachedFunc)
	end

end

function stopToolAnimations()
local oldAnim = toolAnimName

if (currentToolAnimKeyframeHandler ~= nil) then
	currentToolAnimKeyframeHandler:disconnect()
end

toolAnimName = ""
toolAnimInstance = nil
if (toolAnimTrack ~= nil) then
	toolAnimTrack:Stop()
	toolAnimTrack:Destroy()
	toolAnimTrack = nil
end

return oldAnim

end



– STATE CHANGE HANDLERS

function onRunning(speed)
if speed > 0.75 then
local scale = 16.0
playAnimation(“walk”, 0.2, Humanoid)
setAnimationSpeed(speed / scale)
pose = “Running”
else
if emoteNames[currentAnim] == nil and not currentlyPlayingEmote then
playAnimation(“idle”, 0.2, Humanoid)
pose = “Standing”
end
end
end

function onDied()
pose = “Dead”
end

function onJumping()
playAnimation(“jump”, 0.1, Humanoid)
jumpAnimTime = jumpAnimDuration
pose = “Jumping”
end

function onClimbing(speed)
local scale = 5.0
playAnimation(“climb”, 0.1, Humanoid)
setAnimationSpeed(speed / scale)
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 > 1.00 then
local scale = 10.0
playAnimation(“swim”, 0.4, Humanoid)
setAnimationSpeed(speed / scale)
pose = “Swimming”
else
playAnimation(“swimidle”, 0.4, Humanoid)
pose = “Standing”
end
end

function animateTool()
if (toolAnim == “None”) then
playToolAnimation(“toolnone”, toolTransitionTime, Humanoid, Enum.AnimationPriority.Idle)
return
end

if (toolAnim == "Slash") then
	playToolAnimation("toolslash", 0, Humanoid, Enum.AnimationPriority.Action)
	return
end

if (toolAnim == "Lunge") then
	playToolAnimation("toollunge", 0, Humanoid, Enum.AnimationPriority.Action)
	return
end

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

local lastTick = 0

function stepAnimate(currentTime)
local amplitude = 1
local frequency = 1
local deltaTime = currentTime - lastTick
lastTick = currentTime

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
	playAnimation("sit", 0.5, Humanoid)
	return
elseif (pose == "Running") then
	playAnimation("walk", 0.2, Humanoid)
elseif (pose == "Dead" or pose == "GettingUp" or pose == "FallingDown" or pose == "Seated" or pose == "PlatformStanding") then
	stopAllAnimations()
	amplitude = 0.1
	frequency = 1
	setAngles = true
end

-- Tool Animation handling
local tool = Character:FindFirstChildOfClass("Tool")
if tool and tool:FindFirstChild("Handle") then
	local animStringValueObject = getToolAnim(tool)

	if animStringValueObject then
		toolAnim = animStringValueObject.Value
		-- message recieved, delete StringValue
		animStringValueObject.Parent = nil
		toolAnimTime = currentTime + .3
	end

	if currentTime > toolAnimTime then
		toolAnimTime = 0
		toolAnim = "None"
	end

	animateTool()		
else
	stopToolAnimations()
	toolAnim = "None"
	toolAnimInstance = nil
	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)

– setup emote chat hook
game:GetService(“Players”).LocalPlayer.Chatted:connect(function(msg)
local emote = “”
if (string.sub(msg, 1, 3) == "/e ") then
emote = string.sub(msg, 4)
elseif (string.sub(msg, 1, 7) == "/emote ") then
emote = string.sub(msg, 8)
end

if (pose == "Standing" and emoteNames[emote] ~= nil) then
	playAnimation(emote, EMOTE_TRANSITION_TIME, Humanoid)
end

end)

– emote bindable hook
if FFlagAnimateScriptEmoteHook then
script:WaitForChild(“PlayEmote”).OnInvoke = function(emote)
– Only play emotes when idling
if pose ~= “Standing” then
return
end

	if emoteNames[emote] ~= nil then
		-- Default emotes
		playAnimation(emote, EMOTE_TRANSITION_TIME, Humanoid)
		
		return true
	elseif typeof(emote) == "Instance" and emote:IsA("Animation") then
		-- Non-default emotes
		playEmote(emote, EMOTE_TRANSITION_TIME, Humanoid)
		return true
	end
	
	-- Return false to indicate that the emote could not be played
	return false
end

end

– initialize to idle
playAnimation(“idle”, 0.1, Humanoid)
pose = “Standing”

– loop to handle timed state transitions and tool animations
while Character.Parent ~= nil do
local _, currentGameTime = wait(0.1)
stepAnimate(currentGameTime)
end

Please let me know why the default animations are not working. I’m not sure if this is where I should put this, so please redirect me if I’m incorrect. The only issue I can think of is that maybe my animation script is not in the right place. Thanks :smiley:

Hello. I don’t know how to solve this specific problem. But, this topic should be in the (Help and Feedback: Art Design Support)

You would get a lot of help there since it consists of 3D modeling and Meshes. I hope they help you there :slight_smile:

Actually, this would fit in Scripting Support in my opinion. This topic is asking why his scripts isn’t playing animations on the character.

1 Like

Oh, you’re right! Sorry for the inconvenience. :slight_smile:

As this may be a script problem would you please share your script.

I haven’t changed anything in the script at all, but sure I’ll do that now. It may be a placement problem though too.

Have you tried making the “Animate” script serverside?

you’re not going to be able to manipulate a solid mesh with any animations. you need to split it up into each individual bone.

There’s no need to paste the code that you haven’t changed, it clutters the post.

Check that your Motor6Ds are assigned to each connecting part properly. The animation script should be inside ServerScriptService, as it isn’t a local asset, it’s for everyone in the server so it should be in SSS.