Hello. I am trying to create a custom animation script. I have gotten idle, walk, and run animations working. My problem is that when the player runs in circles the speed changes sporadically so the walk animation tries to fade in but doesn’t have time to. I have tried using Roblox’s default animate script for reference, but it didn’t seem to help. The script is very hard to understand.
Video of the issue:
(The number being printed constantly is the player’s speed)
Here is my code (sorry if the variable names aren’t great):
local globals = require(game:GetService("StarterPlayer"):WaitForChild("StarterCharacterScripts"):WaitForChild("Globals"))
local anims = {
-- id becomes a string later on (assetPrefix..id)
["Walk"] = {
id = 13254017584, fadeTime = 0.5, weight = 1
},
["Run"] = {
id = 13254077356, fadeTime = 0.5, weight = 1
},
["Idle"] = {
id = 18440213549, fadeTime = 10, weight = 1
},
}
local char = script:FindFirstAncestorWhichIsA("Model")
local humanoid = char:FindFirstChildWhichIsA("Humanoid")
local animator = humanoid:FindFirstChildWhichIsA("Animator")
local assetPrefix = "rbxassetid://"
local state = "Idle"
if not script:FindFirstChild("Animations") then
local animFolder = Instance.new("Folder")
animFolder.Name = "Animations"
animFolder.Parent = script
end
local function getChildrenWhichAre(parent: Instance, className: string)
local children = {}
for _, child in parent:GetChildren() do
if child:IsA(className) then
table.insert(children, child)
end
end
return children
end
local function convertToAnimTrack(anim): AnimationTrack
local function convertToAnim(val)
if type(val) ~= "number" and type(val) ~= "string" then return nil end
local allAnims = getChildrenWhichAre(script.Animations, "Animation")
for _, v in allAnims do
if v.AnimationId == val or v.AnimationId == assetPrefix..val then
return v
end
end
return nil
end
local animationFound = convertToAnim(anim)
if animationFound then
anim = animator:LoadAnimation(animationFound)
end
if anim:IsA("Animation") then
anim = animator:LoadAnimation(anim)
end
return anim
end
for k, anim in pairs(anims) do
local animFolder: Folder = script.Animations
--check if animation has already been created
local preMadeAnims = getChildrenWhichAre(animFolder, "Animation")
local animPreMade = false
for _, v in preMadeAnims do
local idCheck = v.AnimationId == assetPrefix..anim.id
local nameCheck = v.Name == k
if idCheck or nameCheck then
animPreMade = true
if nameCheck and idCheck then
break
end
if idCheck then
v.Name = k
end
if nameCheck then
v.AnimationId = assetPrefix..anim.id
end
break
end
end
if animPreMade == true then
continue
end
local newAnim = Instance.new("Animation")
newAnim.AnimationId = assetPrefix..anim.id
newAnim.Name = k
newAnim.Parent = animFolder
--convert id into valid AnimationId
anim.id = assetPrefix..anim.id
end
local function getAnimProperties(anim: AnimationTrack)
local animVals = anims[anim.Name]
if animVals then
return animVals
else
warn("Animation does not exist in anims table")
return nil
end
end
local function playAnim(anim, speed)
for _, v in animator:GetPlayingAnimationTracks() do
v:Stop()
end
speed = speed or 1
anim = convertToAnimTrack(anims[anim].id)
local animVals = getAnimProperties(anim)
if not anim.IsPlaying then anim:Play(animVals.fadeTime, animVals.weight) end
end
local function onRunning(speed: number)
print(speed)
if speed > 0.5 then
if speed <= globals.WALKSPEED + 0.1 then
state = "Walk"
playAnim("Walk", speed/globals.WALKSPEED)
elseif speed >= globals.SPRINT_SPEED - 0.1 then
state = "Run"
playAnim("Run", speed/globals.SPRINT_SPEED)
end
else
state = "Idle"
playAnim("Idle", 1)
end
end
humanoid.Running:Connect(onRunning)
Thanks.