Thank you guys much. Also fixed an error where I forgot to call what part
was on line 3.
However, Studio continues to hate my guts, and won’t animate the character.
The Animate script (located where it should be, in the player’s Humanoid
) is:
(NOTE: Where it reads “[CUSTOM ANIMATION]”, these are the number IDs for my animations and are actually filled in on the script properly.)
local Character = script.Parent
local Humanoid = Character:WaitForChild("Humanoid")
local pose = "Standing"
local currentAnim = ""
local currentAnimInstance = nil
local currentAnimTrack = nil
local currentAnimKeyframeHandler = nil
local currentAnimSpeed = 1.0
local runAnimTrack = nil
local runAnimKeyframeHandler = nil
local animTable = {}
local animNames = {
idle = {
{ id = "http://www.roblox.com/asset/?id=[CUSTOM ANIMATION]", weight = 10 }
},
walk = {
{ id = "http://www.roblox.com/asset/?id=[CUSTOM ANIMATION]", weight = 10 }
},
run = {
{ id = "http://www.roblox.com/asset/?id=[CUSTOM ANIMATION]", weight = 10 }
},
swim = {
{ id = "http://www.roblox.com/asset/?id=1083222527", weight = 10 }
},
swimidle = {
{ id = "http://www.roblox.com/asset/?id=1083225406", weight = 10 }
},
jump = {
{ id = "http://www.roblox.com/asset/?id=[CUSTOM ANIMATION]", weight = 10 }
},
fall = {
{ id = "http://www.roblox.com/asset/?id=616157476", weight = 10 }
},
climb = {
{ id = "http://www.roblox.com/asset/?id=1083182000", weight = 10 }
},
sit = {
{ id = "http://www.roblox.com/asset/?id=[CUSTOM ANIMATION]", 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 = "", weight = 10 }
},
point = {
{ id = "", weight = 10 }
},
dance = {
{ id = "", weight = 10 },
{ id = "", weight = 10 },
{ id = "", weight = 10 }
},
dance2 = {
{ id = "", weight = 10 },
{ id = "", weight = 10 },
{ id = "", weight = 10 }
},
dance3 = {
{ id = "", weight = 10 },
{ id = "", weight = 10 },
{ id = "", weight = 10 }
},
laugh = {
{ id = "", weight = 10 }
},
cheer = {
{ id = "", 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 = {}
local allowCustomAnimations = true
local AllowDisableCustomAnimsUserFlag = false
local success, msg = pcall(function()
AllowDisableCustomAnimsUserFlag = UserSettings():IsUserFeatureEnabled("UserAllowDisableCustomAnims2")
end)
if (AllowDisableCustomAnimsUserFlag) then
local success, msg = pcall(function() allowCustomAnimations = game:GetService("StarterPlayer").AllowCustomAnimations end)
if not success then
allowCustomAnimations = true
end
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
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
-- 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 = ""
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
local bodyHeightScale = Humanoid:FindFirstChild("BodyHeightScale")
if bodyHeightScale and bodyHeightScale:IsA("NumberValue") then
return bodyHeightScale.Value
end
end
return 1
end
local smallButNotZero = 0.0001
function setRunSpeed(speed)
if speed < 0.33 then
currentAnimTrack:AdjustWeight(1.0)
runAnimTrack:AdjustWeight(smallButNotZero)
elseif speed < 0.66 then
local weight = ((speed - 0.33) / 0.33)
currentAnimTrack:AdjustWeight(1.0 - weight + smallButNotZero)
runAnimTrack:AdjustWeight(weight + smallButNotZero)
else
currentAnimTrack:AdjustWeight(smallButNotZero)
runAnimTrack:AdjustWeight(1.0)
end
local speedScaled = speed * 1.25
local heightScale = getHeightScale()
runAnimTrack:AdjustSpeed(speedScaled / heightScale)
currentAnimTrack:AdjustSpeed(speedScaled / heightScale)
end
function setAnimationSpeed(speed)
if speed ~= currentAnimSpeed then
currentAnimSpeed = speed
if currentAnim == "walk" then
setRunSpeed(speed)
else
currentAnimTrack:AdjustSpeed(currentAnimSpeed)
end
end
end
function keyFrameReachedFunc(frameName)
if (frameName == "End") then
if currentAnim == "walk" then
runAnimTrack.TimePosition = 0.0
currentAnimTrack.TimePosition = 0.0
else
local repeatAnim = currentAnim
-- return to idle if finishing an emote
if (emoteNames[repeatAnim] ~= nil and emoteNames[repeatAnim] == false) then
repeatAnim = "idle"
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
function playAnimation(animName, transitionTime, humanoid)
local idx = rollAnimation(animName)
local anim = animTable[animName][idx].anim
-- 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()
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
-------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------
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.5 then
local scale = 16.0
playAnimation("walk", 0.2, Humanoid)
setAnimationSpeed(speed / scale)
pose = "Running"
else
if emoteNames[currentAnim] == nil 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")
local requireHandleCheck = not UserSettings():IsUserFeatureEnabled("UserToolR15Fix")
if tool and ((requireHandleCheck and tool.RequiresHandle) or 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, 0.1, Humanoid)
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
I imagine this is failing because I either
- Need to
Destroy()
the animations the player already has (like what @DevSersponge said earlier? clarification might be nice though- in this case, how would I destroy the old animations BEFORE cloning the new Animate script? use wait()
?)
- Was wrong and there is no backwards compatibility on R16 models, and they can’t use R6 animations, which are what my animations are based on. I could bite the bullet and switch the game’s avatar default to R6, or bite the significantly larger bullet and make new R16 animations instead. (If this is the case: is there a way to turn R6 animations to R16? Is there a plugin for this?)
- Some other unknown reason I don’t know applies.
animation painful! im baby.