Animate 2 - A more memory-efficient alternative

Thank you very much! This was my biggest project so far, took me quite a while to make :grin:

1 Like

Ah I see, started to use this for every game is script for! Very optimized and works like a charm.

1 Like

Ironic, because I was just revisiting Animate2 last night for my game. I haven’t used yours yet but it looks better.

2 Likes

looks good to me, I’m sure the performance difference is negligible but its much more readable.

2 Likes

Performance wise, I think there is a (maybe small) improvement over the default script even during gameplay, as the only loop present in Animate 2 is the for loop that is used to load the animations to the Animator. Animate 2 is otherwise event based :slightly_smiling_face:

2 Likes

August 24 Update:

  • Added support for Tool Slash and Lunge animations using the StringValue method
  • Removed the assert previously found on line 2 in order to make it easier for people to experiment with using Animate 2 for NPCs (Unfortunately I can’t guarantee success though, as I’ve only tested Animate 2 on player controlled characters so far)

Maybe name it something else considering this: Animate2 - More readable Animate script
:sweat_smile:

To be honest, I’m not that good at naming things. My priorities are to make sure that if I am to publish a product, it behaves as one would expect it to behave (or at the very least, as advertised :slight_smile:)

2 Likes

Works on r6? I really need a custom animate script

I can’t guarantee it will work for R6, but I did test the R6 zombie NPC and it seemed to be working ok (Although I noticed that the zombie seems to handle the attack animation somewhere different than the default animation script, and I couldn’t find where. I couldn’t get the attack animation to match the default because of this, but other animations like walking were working ok)

Remember to replace the animation id’s with R6 compatible ones :slight_smile:

January 18th, 2024 Update - Animate 2 Version 2:
Bug fixes:

  • Found a way to remove the “You can’t use Emotes here.” error that shows up in TextChatService when using the emotes command
  • Solved an error that shows up if your experience uses Legacy Chat

Improvements:

  • It’s more convenient now to change the default fade time between AnimationTrack and to customize the fade time for a specific track using the optional fadeTime parameter of the new play function
  • Code has been re-written to more closely follow Roblox’s Lua Style guide
  • Type checking is now implemented
Animate 2 Version 2 Source Code
--!strict
local TextChatService = game:GetService("TextChatService")

local DEFAULT_FADE_TIME: number = 0.1

local character: Model = script.Parent
local humanoid = character:WaitForChild("Humanoid"):: Humanoid

local animationTracks: {[string]: AnimationTrack} = {}

do
	local animator = humanoid:WaitForChild("Animator"):: Animator

	local animation = Instance.new("Animation")

	local animationData: {[string]: {any}} = {
		Cheer = {"rbxassetid://507770677", Enum.AnimationPriority.Idle},
		Climb = {"rbxassetid://507765644", Enum.AnimationPriority.Core},
		Dance = {"rbxassetid://507772104", Enum.AnimationPriority.Core},
		Dance2 = {"rbxassetid://507776879", Enum.AnimationPriority.Core},
		Dance3 = {"rbxassetid://507777623", Enum.AnimationPriority.Core},
		Fall = {"rbxassetid://507767968", Enum.AnimationPriority.Core},
		Idle = {"rbxassetid://507766388", Enum.AnimationPriority.Core},
		Laugh = {"rbxassetid://507770818", Enum.AnimationPriority.Idle},
		Lunge = {"rbxassetid://522638767", Enum.AnimationPriority.Movement},
		Point = {"rbxassetid://507770453", Enum.AnimationPriority.Idle},
		Run = {"rbxassetid://913376220", Enum.AnimationPriority.Core},
		Sit = {"rbxassetid://2506281703", Enum.AnimationPriority.Core},
		Slash = {"rbxassetid://522635514", Enum.AnimationPriority.Movement},
		Swim = {"rbxassetid://913384386", Enum.AnimationPriority.Core},
		SwimIdle = {"rbxassetid://913389285", Enum.AnimationPriority.Core},
		Tool = {"rbxassetid://507768375", Enum.AnimationPriority.Idle},
		Wave = {"rbxassetid://507770239", Enum.AnimationPriority.Idle}}

	for name, data in animationData do
		animation.AnimationId = data[1]

		local animationTrack = animator:LoadAnimation(animation)
		animationTrack.Priority = data[2]

		animationTracks[name] = animationTrack
	end

	animation:Destroy()
end

local animationTrack = animationTracks.Idle
animationTrack:Play(0)

local childAddedConnection: RBXScriptConnection?

local round = math.round

local function play(newAnimationTrack: AnimationTrack, fadeTime: number?)
	if newAnimationTrack.IsPlaying then return end

	local fadeTime = fadeTime or DEFAULT_FADE_TIME

	animationTrack:Stop(fadeTime)
	animationTrack = newAnimationTrack
	animationTrack:Play(fadeTime)
end

local function onClimbing(speed: number)
	play(animationTracks.Climb)

	animationTracks.Climb:AdjustSpeed(round(speed) / 11)
end

local function onFreeFalling(active: boolean)
	if active then play(animationTracks.Fall) end
end

local function onRunning(speed: number)
	local speed = round(speed)

	if speed > 0 then
		play(animationTracks.Run)

		animationTracks.Run:AdjustSpeed(speed / 16)
	else
		play(animationTracks.Idle)
	end
end

local function onSeated(active: boolean)
	if active then play(animationTracks.Sit) end
end

local function onSwimming(speed: number)
	local speed = round(speed)

	if speed > 2 then
		play(animationTracks.Swim)

		animationTracks.Swim:AdjustSpeed(speed / 12)
	else
		play(animationTracks.SwimIdle)
	end
end

local function onChildAdded(child: Instance)
	if child:IsA("Tool") and child:FindFirstChild("Handle") then
		animationTracks.Tool:Play(DEFAULT_FADE_TIME)

		childAddedConnection = child.ChildAdded:Connect(function(child: Instance)
			if child:IsA("StringValue") and child.Name == "toolanim" then
				if child.Value == "Slash" then
					animationTracks.Slash:Play(0)
				elseif child.Value == "Lunge" then
					animationTracks.Lunge:Play(0, 1, 6)
				end

				child:Destroy()
			end
		end)
	end
end

local function onChildRemoved(child: Instance)
	if child:IsA("Tool") and child:FindFirstChild("Handle") then
		if childAddedConnection then
			childAddedConnection:Disconnect()
			childAddedConnection = nil
		end

		animationTracks.Tool:Stop(DEFAULT_FADE_TIME)
	end
end

humanoid.Climbing:Connect(onClimbing)
humanoid.FreeFalling:Connect(onFreeFalling)
humanoid.Running:Connect(onRunning)
humanoid.Seated:Connect(onSeated)
humanoid.Swimming:Connect(onSwimming)
character.ChildAdded:Connect(onChildAdded)
character.ChildRemoved:Connect(onChildRemoved)

if TextChatService.ChatVersion == Enum.ChatVersion.TextChatService
and TextChatService.CreateDefaultCommands
and TextChatService.CreateDefaultTextChannels
then
	local rbxEmoteCommand = Instance.new("TextChatCommand")
	rbxEmoteCommand.Name = "RBXEmoteCommand"
	rbxEmoteCommand.PrimaryAlias = "/emote"
	rbxEmoteCommand.SecondaryAlias = "/e"

	local textChatCommands = TextChatService:WaitForChild("TextChatCommands")
	textChatCommands:WaitForChild("RBXEmoteCommand"):Destroy()
	rbxEmoteCommand.Parent = textChatCommands

	local rbxSystem: TextChannel = TextChatService:WaitForChild("TextChannels"):WaitForChild("RBXSystem")

	rbxEmoteCommand.Triggered:Connect(function(_, unfilteredText: string)
		local emote = string.split(unfilteredText, " ")[2]

		if emote == "cheer" then
			animationTracks.Cheer:Play(DEFAULT_FADE_TIME)
		elseif emote == "dance" then
			play(animationTracks.Dance)
		elseif emote == "dance2" then
			play(animationTracks.Dance2)
		elseif emote == "dance3" then
			play(animationTracks.Dance3)
		elseif emote == "laugh" then
			animationTracks.Laugh.Looped = false
			animationTracks.Laugh:Play(DEFAULT_FADE_TIME)
		elseif emote == "point" then
			animationTracks.Point.Looped = false
			animationTracks.Point:Play(DEFAULT_FADE_TIME)
		elseif emote == "wave" then
			animationTracks.Wave.Looped = false
			animationTracks.Wave:Play(DEFAULT_FADE_TIME)
		else
			rbxSystem:DisplaySystemMessage("<font color='#FF4040'>You do not own that emote.</font>")
		end
	end)
end
Animate 2 Version 1 Source Code
local character = script.Parent
local humanoid = character:WaitForChild"Humanoid"
local animator = humanoid:WaitForChild"Animator"

local animationTracks = {
	cheer = {"rbxassetid://507770677", Enum.AnimationPriority.Idle},
	Climb = {"rbxassetid://507765644", Enum.AnimationPriority.Core},
	dance = {"rbxassetid://507772104", Enum.AnimationPriority.Idle},
	dance2 = {"rbxassetid://507776879", Enum.AnimationPriority.Idle},
	dance3 = {"rbxassetid://507777623", Enum.AnimationPriority.Idle},
	Fall = {"rbxassetid://507767968", Enum.AnimationPriority.Core},
	Idle = {"rbxassetid://507766388", Enum.AnimationPriority.Core},
	laugh = {"rbxassetid://507770818", Enum.AnimationPriority.Idle},
	Lunge = {"rbxassetid://522638767", Enum.AnimationPriority.Movement, Play = nil},
	point = {"rbxassetid://507770453", Enum.AnimationPriority.Idle},
	Run = {"rbxassetid://913376220", Enum.AnimationPriority.Core},
	Sit = {"rbxassetid://2506281703", Enum.AnimationPriority.Core},
	Slash = {"rbxassetid://522635514", Enum.AnimationPriority.Movement, Play = nil},
	Swim = {"rbxassetid://913384386", Enum.AnimationPriority.Core},
	SwimIdle = {"rbxassetid://913389285", Enum.AnimationPriority.Core},
	Tool = {"rbxassetid://507768375", Enum.AnimationPriority.Idle, Play = nil},
	wave = {"rbxassetid://507770239", Enum.AnimationPriority.Idle}}

local animation = Instance.new"Animation"

for key, value in animationTracks do
	animation.AnimationId = value[1]

	local animationTrack = animator:LoadAnimation(animation)
	animationTrack.Priority = value[2]
	animationTracks[key] = animationTrack
end
animator, animation = animation:Destroy()

local animationTrack = animationTracks.Idle
animationTrack:Play()

local childAdded

character.ChildAdded:Connect(function(instance)
	if instance:IsA"Tool" and instance:FindFirstChild"Handle" then
		animationTracks.Tool:Play()

		childAdded = instance.ChildAdded:Connect(function(instance)
			if instance:IsA"StringValue" then
				local value = instance.Value

				if value == "Slash" then
					instance:Destroy()
					animationTracks.Slash:Play(0)
				elseif value == "Lunge" then
					instance:Destroy()
					animationTracks.Lunge:Play(0, 1, 6)
				end
			end
		end)
	end
end)

character.ChildRemoved:Connect(function(instance)
	local tool = animationTracks.Tool

	if tool.IsPlaying then
		tool:Stop()
		childAdded = childAdded:Disconnect()
	end
end)
character = nil

humanoid.Climbing:Connect(function(speed)
	local climb = animationTracks.Climb

	if climb.IsPlaying then
		climb:AdjustSpeed(speed / 5)
	else
		animationTrack:Stop()
		animationTrack = climb
		animationTrack:Play()
	end
end)

humanoid.FreeFalling:Connect(function(active)
	if active then
		animationTrack:Stop()
		animationTrack = animationTracks.Fall
		animationTrack:Play()
	end
end)

humanoid.Running:Connect(function(speed)
	speed /= 16

	if speed > 1e-2 then
		local run = animationTracks.Run

		if run.IsPlaying then
			run:AdjustSpeed(speed)
		else
			animationTrack:Stop()
			animationTrack = run
			animationTrack:Play()
		end
	else
		animationTrack:Stop()
		animationTrack = animationTracks.Idle
		animationTrack:Play()
	end
end)

humanoid.Seated:Connect(function(active)
	if active then
		animationTrack:Stop()
		animationTrack = animationTracks.Sit
		animationTrack:Play()
	end
end)

humanoid.Swimming:Connect(function(speed)
	speed /= 10

	if speed > 1 then
		local swim = animationTracks.Swim

		if swim.IsPlaying then
			swim:AdjustSpeed(speed)
		else
			animationTrack:Stop()
			animationTrack = swim
			animationTrack:Play()
		end
	else
		local swimIdle = animationTracks.SwimIdle

		if not swimIdle.IsPlaying then
			animationTrack:Stop()
			animationTrack = swimIdle
			animationTrack:Play()
		end
	end
end)
humanoid = nil

game.TextChatService:WaitForChild"TextChatCommands":WaitForChild"RBXEmoteCommand".Triggered:Connect(function(_, text)
	text = string.split(text, ' ')[2]

	local emotes = {
		cheer = 0,
		dance = 1,
		dance2 = 1,
		dance3 = 1,
		laugh = 0,
		point = 0,
		wave = 0}

	local emote = emotes[text]

	if emote then
		animationTrack:Stop()
		animationTrack = animationTracks[text]

		if emote == 1 then
			animationTrack.Looped = true
			animationTrack:Play()
		else
			animationTrack.Looped = false
			animationTrack:Play()
			animationTrack.Ended:Wait()

			if animationTrack == animationTracks[text] then
				animationTrack = animationTracks.Idle
				animationTrack:Play()
			end
		end
	end
end)
1 Like

I think you did a great job with the script, the issue is the walking animation (under the name Run), is different from roblox’s. Here is a video of the differences. I made sure to make it so animation packs aren’t used for the roblox default one.
Your script, Animate 2:


Roblox’s default Animate script:

1 Like

It’s because you can change the running animation of your avatar on roblox, I think @JohhnyLegoKing forgot about that.
You might have to get the player’s run animation somehow and put it on the script to solve this bug.

I mean because the animate 2 running animation is the same than the default running animation.

2 Likes

Currently Animate 2 doesn’t have a convenient way to implement per-player animations, so the animation IDs found in the animationData table on line 16 will be used for all players within your game

If you wish to change the run animation to one used by a different package, here’s what you need to do:

  1. Equip the package containing the run animation you’d like to use to your character on the Roblox website
  2. Go to a new empty baseplate in Studio and press play
  3. In the Explorer, go to: Workspace → Your character → The default Animate script → run → RunAnim
  4. Copy the RunAnim’s AnimationId and paste it in a text editor like notepad
  5. Go back to your game that uses Animate 2 and find line 27
  6. Change the animation ID to the one previously pasted to the text editor

Do note that following these steps will change the run animation for every player in your game

@BrAlMeSo_Mc I’ll see if I can find a way to make Animate 2 accept different animation packages, but it will take a while to thoroughly test any changes :sweat_smile:

With the help of @InfiniteYield I managed to make a version of Animate 2 that’s compatible with Roblox’s animation packages/bundles (although I was unable to upload it to the marketplace due to an unknown error, possibly due to the fact that this version uses InsertService)

This is what you need to do:

  1. Add a RemoteFunction named AnimationIDRequest to ReplicatedStorage
  2. Add a server Script to ServerScriptService and inside of it write:
--!strict
local InsertService = game:GetService("InsertService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local animationIDRequest = ReplicatedStorage.AnimationIDRequest

local function onAnimationIDRequest(_, assetID: number)
	if typeof(assetID) == "number" then
		local success, model = pcall(InsertService.LoadAsset, InsertService, assetID)

		if success then
			for _, instance in model:GetDescendants() do
				if instance:IsA("Animation") then return instance.AnimationId end
			end
		end
	end
end

animationIDRequest.OnServerInvoke = onAnimationIDRequest
  1. Replace the code inside of my Animate LocalScript with:
--!strict
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TextChatService = game:GetService("TextChatService")

local DEFAULT_FADE_TIME: number = 0.1

local character: Model = script.Parent
local humanoid = character:WaitForChild("Humanoid"):: Humanoid

local animationTracks: {[string]: AnimationTrack} = {}

do
	local animationIDRequest = ReplicatedStorage:WaitForChild("AnimationIDRequest")

	local animator = humanoid:WaitForChild("Animator"):: Animator

	local humanoidDescription = humanoid:WaitForChild("HumanoidDescription"):: HumanoidDescription

	local animation = Instance.new("Animation")

	local function getAnimationID(descriptionID: number, defaultID: string): string
		if descriptionID == 0 then return defaultID end

		local animationID = animationIDRequest:InvokeServer(descriptionID)

		return if animationID then animationID else defaultID
	end

	local animationData: {[string]: {any}} = {
		Cheer = {"rbxassetid://507770677", Enum.AnimationPriority.Idle},
		Climb = {getAnimationID(humanoidDescription.ClimbAnimation, "rbxassetid://507765644"), Enum.AnimationPriority.Core},
		Dance = {"rbxassetid://507772104", Enum.AnimationPriority.Core},
		Dance2 = {"rbxassetid://507776879", Enum.AnimationPriority.Core},
		Dance3 = {"rbxassetid://507777623", Enum.AnimationPriority.Core},
		Fall = {getAnimationID(humanoidDescription.FallAnimation, "rbxassetid://507767968"), Enum.AnimationPriority.Core},
		Idle = {getAnimationID(humanoidDescription.IdleAnimation, "rbxassetid://507766388"), Enum.AnimationPriority.Core},
		Laugh = {"rbxassetid://507770818", Enum.AnimationPriority.Idle},
		Lunge = {"rbxassetid://522638767", Enum.AnimationPriority.Movement},
		Point = {"rbxassetid://507770453", Enum.AnimationPriority.Idle},
		Run = {getAnimationID(humanoidDescription.RunAnimation, "rbxassetid://913376220"), Enum.AnimationPriority.Core},
		Sit = {"rbxassetid://2506281703", Enum.AnimationPriority.Core},
		Slash = {"rbxassetid://522635514", Enum.AnimationPriority.Movement},
		Swim = {getAnimationID(humanoidDescription.SwimAnimation, "rbxassetid://913384386"), Enum.AnimationPriority.Core},
		SwimIdle = {"rbxassetid://913389285", Enum.AnimationPriority.Core},
		Tool = {"rbxassetid://507768375", Enum.AnimationPriority.Idle},
		Wave = {"rbxassetid://507770239", Enum.AnimationPriority.Idle}}

	for name, data in animationData do
		animation.AnimationId = data[1]

		local animationTrack = animator:LoadAnimation(animation)
		animationTrack.Priority = data[2]

		animationTracks[name] = animationTrack
	end

	animation:Destroy()
end

local animationTrack = animationTracks.Idle
animationTrack:Play(0)

local childAddedConnection: RBXScriptConnection?

local round = math.round

local function play(newAnimationTrack: AnimationTrack, fadeTime: number?)
	if newAnimationTrack.IsPlaying then return end

	local fadeTime = fadeTime or DEFAULT_FADE_TIME

	animationTrack:Stop(fadeTime)
	animationTrack = newAnimationTrack
	animationTrack:Play(fadeTime)
end

local function onClimbing(speed: number)
	play(animationTracks.Climb)

	animationTracks.Climb:AdjustSpeed(round(speed) / 11)
end

local function onFreeFalling(active: boolean)
	if active then play(animationTracks.Fall) end
end

local function onRunning(speed: number)
	local speed = round(speed)

	if speed > 0 then
		play(animationTracks.Run)

		animationTracks.Run:AdjustSpeed(speed / 16)
	else
		play(animationTracks.Idle)
	end
end

local function onSeated(active: boolean)
	if active then play(animationTracks.Sit) end
end

local function onSwimming(speed: number)
	local speed = round(speed)

	if speed > 2 then
		play(animationTracks.Swim)

		animationTracks.Swim:AdjustSpeed(speed / 12)
	else
		play(animationTracks.SwimIdle)
	end
end

local function onChildAdded(child: Instance)
	if child:IsA("Tool") and child:FindFirstChild("Handle") then
		animationTracks.Tool:Play(DEFAULT_FADE_TIME)

		childAddedConnection = child.ChildAdded:Connect(function(child: Instance)
			if child:IsA("StringValue") and child.Name == "toolanim" then
				if child.Value == "Slash" then
					animationTracks.Slash:Play(0)
				elseif child.Value == "Lunge" then
					animationTracks.Lunge:Play(0, 1, 6)
				end

				child:Destroy()
			end
		end)
	end
end

local function onChildRemoved(child: Instance)
	if child:IsA("Tool") and child:FindFirstChild("Handle") then
		if childAddedConnection then
			childAddedConnection:Disconnect()
			childAddedConnection = nil
		end

		animationTracks.Tool:Stop(DEFAULT_FADE_TIME)
	end
end

humanoid.Climbing:Connect(onClimbing)
humanoid.FreeFalling:Connect(onFreeFalling)
humanoid.Running:Connect(onRunning)
humanoid.Seated:Connect(onSeated)
humanoid.Swimming:Connect(onSwimming)
character.ChildAdded:Connect(onChildAdded)
character.ChildRemoved:Connect(onChildRemoved)

if TextChatService.ChatVersion == Enum.ChatVersion.TextChatService
and TextChatService.CreateDefaultCommands
and TextChatService.CreateDefaultTextChannels
then
	local rbxEmoteCommand = Instance.new("TextChatCommand")
	rbxEmoteCommand.Name = "RBXEmoteCommand"
	rbxEmoteCommand.PrimaryAlias = "/emote"
	rbxEmoteCommand.SecondaryAlias = "/e"

	local textChatCommands = TextChatService:WaitForChild("TextChatCommands")
	textChatCommands:WaitForChild("RBXEmoteCommand"):Destroy()
	rbxEmoteCommand.Parent = textChatCommands

	local rbxSystem: TextChannel = TextChatService:WaitForChild("TextChannels"):WaitForChild("RBXSystem")

	rbxEmoteCommand.Triggered:Connect(function(_, unfilteredText: string)
		local emote = string.split(unfilteredText, " ")[2]

		if emote == "cheer" then
			animationTracks.Cheer:Play(DEFAULT_FADE_TIME)
		elseif emote == "dance" then
			play(animationTracks.Dance)
		elseif emote == "dance2" then
			play(animationTracks.Dance2)
		elseif emote == "dance3" then
			play(animationTracks.Dance3)
		elseif emote == "laugh" then
			animationTracks.Laugh.Looped = false
			animationTracks.Laugh:Play(DEFAULT_FADE_TIME)
		elseif emote == "point" then
			animationTracks.Point.Looped = false
			animationTracks.Point:Play(DEFAULT_FADE_TIME)
		elseif emote == "wave" then
			animationTracks.Wave.Looped = false
			animationTracks.Wave:Play(DEFAULT_FADE_TIME)
		else
			rbxSystem:DisplaySystemMessage("<font color='#FF4040'>You do not own that emote.</font>")
		end
	end)
end

Dance2 is playing forever on others’ view for some reason???

The issue I showcased isnt due to custom bundles. I actually just enabled the option to use roblox’s default animation pack, inside of gamesettings (shown below), I expected animation packs not to work, but I am just saying the animation in the animate 2 script for Run is different, and I think uses an older version of the script.

Though to support bundles wouldnt be much difficult and wont require the steps you did provide (which is nice though, by the way), as roblox ApplyDescription actually creates children in the current Animate script with changes to the animations of each type. Example shown in video below. Basically when roblox loads the character if the player has a custom animation bundle and the game allows it, itll place a bunch of IntValues under the Animate script, so you can update Animate 2 just to use those Animations. this will make it more complex, and is actually part of the reason Roblox’s default one is 1k lines almost, as Roblox will first check if the IntValue exists or is added and load the entire list, along with weights to essentially dictate the randomness of a certain animation playing, an example would be Idle animations, which usually have 2 or more per animation bundle, with a basic looping one, and a couple (or at least 1) Idle animation that plays occasionally, like the idle animation where the player looks around and then goes back to the looped idle animation.


Image shows Game Settings in studio with a choice for Standard Animation on player avatars. In my original reply about differences in the run animation was bc the Standard Animation option here has a different Run animation than the default inside of Animate 2.


This video I use basically an empty Animate script to showcase the fact that roblox will place a bunch of IntValues in the Animate script when a HumanoidDescription is applied, and when you change the animations via Humanoid methods to do so. I also showcase that with Standard animations selected, it actually doesnt add any of those IntValues (other than a basic Dampening one I have no clue what it does in the default script), This means the animation ids in the roblox standard Animate script are defaults and Animate 2 uses a different one for Run, as my original reply showcases.

Roblox’s default Animate script also creates children IntValues inside of itself, assumably so different scripts outside of the Animate script can modify the other animations aswell. (Such as it providing a slash animation IntValue, even though animation packs dont have a slash animation)

1 Like

I was able to replicate this issue

I strongly suspect this is a bug since I can verify that Animate 2 was working correctly until the most recent update, so I will make a report as soon as possible

If anyone has more information about this, please let me know. Thank you

1 Like

My intent for Animate 2 is to be a more lightweight, memory-efficient and relatively simple alternative to the default animation script, but this came at a cost of removing some of the functionality as you correctly noted :sweat_smile:

The ideal use-case for Animate 2 are games with a set animation style (as in, predetermined by the game developer), which won’t require the other capabilities the default animation script provides thus will save a bit of memory and hopefully also gain a slight performance improvement by using Animate 2

March 24th, 2024 Update
Bug fix:

  • Found a solution to the problem of animations replicating incorrectly for other players

@sonicdoidao2004 You’ll enjoy this update :grin:


More details about the bug fix:

1 Like