AnimatedMesh objects are skeletal CoreMeshes with parameterized animations baked into them. They also have sockets exposed to which any CoreObject can be attached.
|Property Name||Return Type||Description||Tags|
| || ||The stance the animated mesh plays.||Read-Write, Client-Only|
| || ||The playback rate for the animation stance being played.||Read-Write, Client-Only|
| || ||If ||Read-Write, Client-Only|
| || ||Rate multiplier for all animations played on the animated mesh. Setting this to ||Read-Write, Client-Only|
|Function Name||Return Type||Description||Tags|
| || ||Returns an array of all available animations on this object.||None|
| || ||Returns an array of all available animation stances on this object.||None|
| || ||Returns an array of all available sockets on this object.||None|
| || ||Returns an array of available animation event names for the specified animation. Raises an error if ||None|
| || ||Attaches the specified object to the specified socket on the mesh if they exist.||Client-Only|
| || ||Plays an animation on the animated mesh. |
Optional parameters can be provided to control the animation playback:
| || ||Stops all in-progress animations played via ||Client-Only|
| || ||Returns the duration of the animation in seconds. Raises an error if ||None|
| || ||Returns the asset ID of the mesh assigned to the specified slot on this ||Client-Only|
| || ||Assigns a mesh to the specified slot on this ||Client-Only|
| || ||Set the material in the given slot to the material specified by assetId.||None|
| || ||Get the MaterialSlot object for the given slot. If called on the client on a networked object, the resulting object cannot be modified.||None|
| || ||Get an array of all MaterialSlots on this mesh. If called on the client on a networked object, the resulting object cannot be modified.||None|
| || ||Resets a material slot to its original state.||None|
|Event Name||Return Type||Description||Tags|
| || ||Some animations have events specified at important points of the animation (e.g. the impact point in a punch animation). This event is fired with the animated mesh that triggered it, the name of the event at those points, and the name of the animation itself.||Client-Only|
Some animations have events that fire when certain parts of the animations are reached. This allows you to sync up hit effects with animations. Important note! This event is only fired client side. The server cannot directly respond to animation events!
local propDragonMob = script:GetCustomProperty("DragonMob") local dragonMesh = World.SpawnAsset(propDragonMob) function AnimEventListener(mesh, eventName) print("Animated Mesh " .. mesh.name .. " just hit event " .. eventName .. "!") -- Normally we'd spawn a "Swipe" effect here, and possibly check if we hit a player! end dragonMesh.animationEvent:Connect(AnimEventListener) dragonMesh:PlayAnimation("unarmed_claw")
Attaches the specified object to the specified socket on the mesh if they exist.
In this example, we want to attach multiple objects to an animated mesh to create a costume, such as equipment on a skeleton enemy or horns on the head of a raptor. For it to work, setup the animated mesh in its "binding" stance and without any animations playing at the start. Place this script along with any costume parts to be attached as children of the animated mesh. Position and rotate the costume parts to align them with their destinations on the mesh. The costume parts are expected to be groups/folders with their names matching the socket names they are destined to. When the script runs, it searches through all the mesh's children and attaches them to the sockets.
local MESH = script.parent local allObjects = MESH:GetChildren() for _, obj in ipairs(allObjects) do if obj:IsA("Folder") then local socketName = obj.name local pos = obj:GetWorldPosition() local rot = obj:GetWorldRotation() MESH:AttachCoreObject(obj, socketName) obj:SetWorldPosition(pos) obj:SetWorldRotation(rot) end end
You can find out most of the interesting data about an Animated Mesh at runtime, using several handy functions.
local propDragonMob = script:GetCustomProperty("DragonMob") -- This function prints out all of the animations, sockets, stances, and events associated -- with an animated mesh! function PrintAnimatedMeshData(mesh) print("Animation names:") for _, v in ipairs(mesh:GetAnimationNames()) do print(" " .. v .. "(" .. tostring(mesh:GetAnimationDuration(v)) .. ")") -- Print out any events that are associated with this animation: for _,e in ipairs(mesh:GetAnimationEventNames(v)) do print(" Event: " .. e) end end print("\nAnimation stance names:") for _, v in ipairs(mesh:GetAnimationStanceNames()) do print(" " .. v) end print("\nSocket names:") for _, v in ipairs(mesh:GetSocketNames()) do print(" " .. v) end end local dragonMesh = World.SpawnAsset(propDragonMob) PrintAnimatedMeshData(dragonMesh)
In this example, a client script copies the mesh slots from one
AnimatedMesh to another.
local ANIM_MESH_1 = script:GetCustomProperty("AnimMesh1"):WaitForObject() local ANIM_MESH_2 = script:GetCustomProperty("AnimMesh2"):WaitForObject() function Clear(animMesh) animMesh:SetMeshForSlot(1, "") animMesh:SetMeshForSlot(2, "") animMesh:SetMeshForSlot(3, "") animMesh:SetMeshForSlot(4, "") end function CopyMeshAtSlot(slotIndex) local mesh = ANIM_MESH_1:GetMeshForSlot(slotIndex) if mesh then ANIM_MESH_2:SetMeshForSlot(slotIndex, mesh) end end Clear(ANIM_MESH_2) CopyMeshAtSlot(1) CopyMeshAtSlot(2) CopyMeshAtSlot(3) CopyMeshAtSlot(4)
Plays an animation on the animated mesh. Optional parameters can be provided to control the animation playback:
playbackRate (Number): Controls how fast the animation plays.
shouldLoop (bool): If
true, the animation will keep playing in a loop. If
false the animation will stop playing once completed.
In this example, a humanoid animated mesh has its laughing and death animations controlled by pressing the primary and secondary action bindings (PC default is mouse left-click and right-click respectively).
local MESH = script.parent function PlayAttack() MESH:PlayAnimation("unarmed_laugh") MESH.playbackRateMultiplier = 1 end function PlayDeath() MESH:PlayAnimation("unarmed_death") Task.Wait(1.96) -- Prevents the animation from looping or returning to stance MESH.playbackRateMultiplier = 0 end function OnBindingPressed(player, action) if action == "ability_primary" then PlayAttack() elseif action == "ability_secondary" then PlayDeath() end end Game.playerJoinedEvent:Connect(function(player) player.bindingPressedEvent:Connect(OnBindingPressed) end)
You can stop whatever animation is currently playing via
local propDragonMob = script:GetCustomProperty("DragonMob") local dragonMesh = World.SpawnAsset(propDragonMob) dragonMesh:PlayAnimation("unarmed_slash") Task.Wait(0.25) dragonMesh:StopAnimations()
In this example an NPC's body material is temporarily set to very bright when the function
ShowStatusColor() is called. After a little time, it's set back to normal. We keep count of active status effects with the variable
statusCount, so in case multiple calls to show the status color overlap during the wait time the material is not reset prematurely.
local ANIM_MESH = script.parent local SLOT_NAME = "0:Shared_BaseMaterial" local DURATION = 1.5 local statusCount = 0 function ShowStatusColor() local slot = ANIM_MESH:GetMaterialSlot(SLOT_NAME) if slot then slot:SetColor(Color.WHITE * 10) --Very bright statusCount = statusCount + 1 Task.Wait(DURATION) statusCount = statusCount - 1 if statusCount <= 0 then ANIM_MESH:ResetMaterialSlot(SLOT_NAME) end else print("No slot found with name " .. SLOT_NAME) end end
In this example an NPC's material is changed at runtime. The script is placed as a child of the NPC's animated mesh and the desired material is assigned to the script as a custom property.
local ANIM_MESH = script.parent local MATERIAL = script:GetCustomProperty("Material") local matSlot = ANIM_MESH:GetMaterialSlots() ANIM_MESH:SetMaterialForSlot(MATERIAL, matSlot.slotName)
The stance the animated mesh plays.
This example demonstrates how to dynamically control the walking stances and to vary their playback speed by how fast the character is moving. This script itself does not move the mesh--that is expected to happen in another script such as an AI or simple
local MESH = script.parent -- 0.9 is an approximate scale for the Fox mesh -- 2 is an approximate for the Raptor and humanoids local WALK_SCALE = 2 local RUN_BASE = 0.5 local RUN_SCALE = 0.002 -- Thresholds of speed (cm/s) that define which stance to use local WALKING_SPEED = 15 local RUNNING_SPEED = 300 local lastPos = MESH:GetWorldPosition() function Tick(deltaTime) if deltaTime <= 0 then return end local pos = MESH:GetWorldPosition() local direction = pos - lastPos local speed = direction.size / deltaTime -- We can make sure the animation stance loops. If we wanted it to only -- play once, we would set it to false here. MESH.animationStanceShouldLoop = true lastPos = pos if speed < WALKING_SPEED then MESH.animationStance = "unarmed_idle_ready" elseif speed < RUNNING_SPEED then MESH.animationStance = "unarmed_walk_forward" MESH.animationStancePlaybackRate = WALK_SCALE * (speed - WALKING_SPEED) / (RUNNING_SPEED - WALKING_SPEED) else MESH.animationStance = "unarmed_run_forward" MESH.animationStancePlaybackRate = RUN_BASE + (speed - RUNNING_SPEED) * RUN_SCALE end end