I have a spear in my game, and I have 2 animations for it.
Idle, and Attack.
Idle is obviously set to Idle priority.
Attack is set to Action priority.
For some reason I can’t seem to figure out, the Idle animation is winning out against the Attack animation for just a single frame at the begginning when it first plays.
The reason I put this in scripting support is because the animations work fine on their own, but when I put them together with a script they jitter like this, I’m not ruling out the possibility that my script it bad, so here’s that:
local IdleAnim
local SwingAnim = nil
local BlockAnim
local LastSwing = 0
local ClickEvent
local WeaponsOut = false
local Debounce = false
local AttackDebounce = false
local BlockSpeed = 10
local AttackCooldown = 0.4
function IsRunning()
local MoveDirection = Player.Character.Humanoid.MoveDirection
return CS.GetState() == "Running" and (MoveDirection - Vector3.new(0, MoveDirection.Y, 0)).Magnitude > 0.1
end
function UpdateSwingStates(Weapon)
if ClickEvent then ClickEvent:Disconnect() end
if SwingAnim then SwingAnim:Stop() end
if IdleAnim then IdleAnim:Stop() end
SwingAnim = Player.Character.Humanoid:LoadAnimation(Weapon.Attack)
local MaxSwings = Weapon.Swings.Value
ClickEvent = SwingAnim:GetMarkerReachedSignal("Click"):Connect(function(Number)
if not WM.Equipped() then return end
if tonumber(Number) == 1 then LastSwing = tick() end
if tonumber(Number) >= MaxSwings then
IdleAnim:Play()
AttackDebounce = true
wait(AttackCooldown)
WM.SetState("Attacking", false)
CS.SetState("Idle")
wait(AttackCooldown)
AttackDebounce = false
else
SwingAnim:AdjustSpeed(0)
spawn(function()
wait(AttackCooldown)
if not WM.Equipped() then return end
if tick() - LastSwing > AttackCooldown then
IdleAnim:Play()
SwingAnim:Stop()
WM.SetState("Attacking", false)
CS.SetState("Idle")
wait(AttackCooldown)
AttackDebounce = false
end
end)
end
end)
end
function CalculateAnim(Weapon, Shield)
local State = CS.GetState()
if State == "Knocked" then
return
elseif State == "Casting" then
-- Need to make this a more WeaponModule oriented thing so that in the future when more thing rely on having the weapon out, it'll be easy to know.
WM.Unequip()
WeaponsOut = false
elseif State == "Running" then
if Weapon then
if Shield then
if WM.Blocking() then
Player.Character.Humanoid.WalkSpeed = BlockSpeed
CS.SetState("Blocking")
return script.ShieldBlock
else
return script.Run
end
else
if WM.Blocking() then
Player.Character.Humanoid.WalkSpeed = BlockSpeed
CS.SetState("Blocking")
return script.WeaponBlock
else
return script.Run
end
end
end
if Shield then
if WM.Blocking() then
Player.Character.Humanoid.WalkSpeed = BlockSpeed
CS.SetState("Blocking")
return script.ShieldBlock
end
end
elseif State == "Idle" then
if Weapon then
if Shield then
if WM.Blocking() then
Player.Character.Humanoid.WalkSpeed = BlockSpeed
CS.SetState("Blocking")
return script.ShieldBlock
else
local Anim = Weapon:FindFirstChild("Idle")
if Anim then return Anim end
end
else
if WM.Blocking() then
Player.Character.Humanoid.WalkSpeed = BlockSpeed
return script.WeaponBlock
else
local Anim = Weapon:FindFirstChild("Idle")
if Anim then return Anim end
end
end
end
end
end
CS.Changed(function(State)
local Character = Player.Character
if WeaponsOut then
if IdleAnim then IdleAnim:Stop() end
local Weapon = Character:FindFirstChild("Weapon")
local Shield = Character:FindFirstChild("Shield")
local Anim = CalculateAnim(Weapon, Shield)
if Anim then
IdleAnim = Character.Humanoid:LoadAnimation(Anim)
IdleAnim:Play()
end
end
end)
WM.OnUnequip(function()
WeaponsOut = false
end)
UIS.InputBegan:Connect(function(Input, IsTyping)
if IsTyping or Credits.Enabled or Debounce then return end
local Character = Player.Character
if Input.KeyCode == KeyBinds.GetBinds()['Spirit Weapons'] then
Debounce = true
spawn(function() wait(1.2) Debounce = false end)
WeaponsOut = WM.Toggle(not WeaponsOut)
if IdleAnim then IdleAnim:Stop() end
if WeaponsOut then
local Weapon = Character:FindFirstChild("Weapon")
local Shield = Character:FindFirstChild("Shield")
local Anim = CalculateAnim(Weapon, Shield)
if Anim then
spawn(function()
if Weapon then
local SavedState = CS.GetState()
CS.SetState("Equipping")
local EquipAnim = Character.Humanoid:LoadAnimation(script.Equip)
EquipAnim:Play()
wait(0.5)
if CS.GetState() == "Equipping" then CS.SetState(SavedState) end
end
if IdleAnim then IdleAnim:Stop() end
IdleAnim = Character.Humanoid:LoadAnimation(Anim)
IdleAnim:Play()
end)
end
if Weapon or Shield then
WM.SetState("Equipped", true)
if Weapon then UpdateSwingStates(Weapon) end
else
WM.SetState("Equipped", false)
end
else
WM.SetState("Equipped", false)
WM.SetState("Attacking", false)
WM.SetState("Blocking", false)
CS.SetState("Idle") -- Kinda bad, but not really since Idle and Running are very similar anyway.
if Character:FindFirstChild("Humanoid") then Character.Humanoid.WalkSpeed = game:GetService("StarterPlayer").CharacterWalkSpeed end
if IdleAnim then IdleAnim:Stop() end
if BlockAnim then BlockAnim:Stop() end
if SwingAnim then SwingAnim:Stop() end
end
end
end)
Mouse.Button1Down:Connect(function()
if WM.Blocking() or not WM.Equipped() or AttackDebounce then return end
local Weapon = Player.Character:FindFirstChild("Weapon")
if Weapon then
local AttackSpeed = 1 -- In the future set this to some multiple of the users dexterity.
WM.SetState("Attacking", true)
CS.SetState("Attacking")
if not SwingAnim.IsPlaying then SwingAnim:Play() end
SwingAnim:AdjustSpeed(AttackSpeed)
LastSwing = tick()
end
end)
Mouse.Button2Down:Connect(function()
if not WM.Equipped() then return end
WM.SetState("Blocking", true)
WM.SetState("Attacking", false)
local Humanoid = Player.Character.Humanoid
local Weapon = Player.Character:FindFirstChild("Weapon")
local Shield = Player.Character:FindFirstChild("Shield")
local Anim = CalculateAnim(Weapon, Shield)
if SwingAnim then SwingAnim:Stop() end
if IdleAnim then IdleAnim:Stop() end
if Humanoid and Anim then BlockAnim = Humanoid:LoadAnimation(Anim) end
if BlockAnim then BlockAnim:Play() end
end)
Mouse.Button2Up:Connect(function()
WM.SetState("Blocking", false)
if WM.Equipped() then
CS.SetState("Idle")
local Humanoid = Player.Character.Humanoid
Humanoid.WalkSpeed = game:GetService("StarterPlayer").CharacterWalkSpeed
if BlockAnim then BlockAnim:Stop() end
end
end)
It makes it look jittery, like this:
But I want it to look like this:
Here’s the idle animation for reference:
So a quick recap, for some reason the Idle animation makes the player jitter between Idle and Attack for a single frame when Attack first starts up. I’ve already preloaded Attack, so it’s not an issue of loading.
Does anyone know why this is happening?