Npc's animation really weird

I’m currently making a roblox game and i asked chatGPT to code me 2 dancing npcs that should display the 2 best players for 2 leaderstats. everything works well, except for the fact that the animation list kinda fuses together for some reasons… i asked chatgpt to make it some sort of list, so that it starts from the first one and goes to the last, and after it goes back to the first animationId. I KNOW that this script may not be the best, and dont judge me for using chatGPT (please).

this is my script:

local players = game:GetService("Players")
local datastoreservice = game:GetService("DataStoreService")
local database = datastoreservice:GetDataStore("database")
local leaderboard = datastoreservice:GetOrderedDataStore("leaderboard")

-- List of animation IDs that you want to switch between
local animationIds = {
	14022936101, -- yungblud
	10714349037,
	10714377090,
	-- Add more animation IDs here
}

-- Function to select a random animation ID
local currentIndex = 1

local function getNextAnimationId()
	local nextIndex = currentIndex
	currentIndex = currentIndex % #animationIds + 1
	return animationIds[nextIndex]
end

local function playAnimation(humanoid, animationId)
	local animation = Instance.new("Animation")
	animation.AnimationId = "rbxassetid://" .. animationId
	local animationTrack = humanoid:LoadAnimation(animation)

	animationTrack:Play()
	animationTrack:Destroy() -- Destroy the AnimationTrack after playing
end


function format(value)
	local formatted = value
	while true do
		local formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2')
		if (k == 0) then
			break
		end
	end
	return formatted
end

local function loadPlayerCharacter(humanoid, userId)
	local player = players:GetPlayerByUserId(userId)
	if player then
		local character = player.Character
		if not character then
			player.CharacterAdded:Connect(function(char)
				humanoid = char:WaitForChild("Humanoid")
				humanoid.Died:Connect(function()
					wait(5) -- Wait for 5 seconds before respawning
					player:LoadCharacter()
				end)
			end)
			wait(2) -- Wait for 2 seconds before loading the character
			player:LoadCharacter()
		else
			humanoid.Died:Connect(function()
				wait(5) -- Wait for 5 seconds before respawning
				player:LoadCharacter()
			end)

			local Appearance = players:GetHumanoidDescriptionFromUserId(userId)

			-- {{ SIZING
			Appearance.HeightScale = 1.325
			Appearance.DepthScale = 1.325
			Appearance.ProportionScale = 1.325
			Appearance.BodyTypeScale = 1.325
			Appearance.HeadScale = 1.5
			Appearance.WidthScale = 1.325
			humanoid:ApplyDescription(Appearance)

			-- Play the animation
			local animator = humanoid:FindFirstChild("Animator")
			if animator then
				local nextAnimationId = getNextAnimationId()
				playAnimation(animator, nextAnimationId)
			else
				warn("Animator not found for player " .. userId)
			end
		end
	else
		warn("Player with UserID " .. userId .. " not found")
	end
end

local function getLeaderstatValue(player, leaderstatName)
	if player and player:FindFirstChild("leaderstats") then
		local leaderstats = player.leaderstats
		local leaderstat = leaderstats:FindFirstChild(leaderstatName)

		if leaderstat then
			return leaderstat.Value
		else
			warn(leaderstatName .. " leaderstat not found for player " .. player.UserId)
		end
	else
		warn("Leaderstats not found for player " .. player.UserId)
	end
	return 0
end


local function getPurchasesValue(userId)
	local player = players:GetPlayerByUserId(userId)
	return player and getLeaderstatValue(player, "Purchases") or 0
end

local function getSpentValue(userId)
	local player = players:GetPlayerByUserId(userId)
	return player and getLeaderstatValue(player, "Spent") or 0
end

while true do
	for i, v in pairs(leaderboard:GetSortedAsync(false, 3, 1):GetCurrentPage()) do
		local userId = v.key
		local rank = tostring(i)
		local value = v.value
		local playerName = players:GetNameFromUserIdAsync(userId)
		local placeStatueA = workspace.Map.UndeletableStuff.Leaderboards.StatueA
		local placeStatueB = workspace.Map.UndeletableStuff.Leaderboards.StatueB
		local playerImage = game.Players:GetUserThumbnailAsync(userId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size420x420)

		if placeStatueA and placeStatueB then
			local humanoidA = placeStatueA.Statue.Humanoid
			local humanoidB = placeStatueB.Statue.Humanoid
			local humanoidAStats = placeStatueA.Stats
			local humanoidBStats = placeStatueB.Stats

			if humanoidA and humanoidB then
				-- Determine the next animation IDs for each humanoid
				local nextAnimationIdA = getNextAnimationId()
				local nextAnimationIdB = getNextAnimationId()

				-- Load player character for each humanoid
				loadPlayerCharacter(humanoidA, userId)
				loadPlayerCharacter(humanoidB, userId)

				-- Play the animations for each humanoid
				playAnimation(humanoidA, nextAnimationIdA)
				playAnimation(humanoidB, nextAnimationIdB)

				-- Update stats for humanoid A
				local spentValue = getSpentValue(userId)

				local formattedSpent = format(spentValue)
				humanoidAStats.BillboardGui.Frame.PlayerName.Text = "#" .. rank .. ": " .. playerName
				humanoidAStats.BillboardGui.Frame.PlayerImage.Image = playerImage
				humanoidAStats.BillboardGui.Frame.MoneyAmount.Text = "Spent: " .. formattedSpent .. " R$!"

				local purchasesValue = getPurchasesValue(userId)

				local formattedPurchases = format(purchasesValue)
				humanoidBStats.BillboardGui.Frame.PlayerName.Text = "#" .. rank .. ": " .. playerName
				humanoidBStats.BillboardGui.Frame.PlayerImage.Image = playerImage
				humanoidBStats.BillboardGui.Frame.MoneyAmount.Text = formattedPurchases .. "Purchases!"
			else
				warn("Humanoids not found for place " .. rank)
			end
		end
	end

	wait(20) -- Wait for 20 seconds before updating again
end

Hey! We generally don’t like to help people using ChatGPT or youtube videos as it isn’t their code. This is a place for you to learn scripting and grow as a programmer, not get free labor from helpers. You could try to make the system wait after playing the animations and updating the BillboardGui.

3 Likes

True, ChatGPT sometimes generates incorrect code so I wouldn’t recommend using it, even if you are you should still know how to modify the code incase of errors in the code or to add more lines of code.

It’s fine to ask for help, even if you have used GPT - I doubt that’s a new rule of this subforum that I’m not aware of.

I would, however, agree that you should at least try to read the code it produces; LLMs like ChatGPT aren’t infallible - this is evidenced by the code given to you being incorrect:

ChatGPT has helpfully added a comment for you to read here: “Destroy the animation track after playing

This doesn’t actually do what it states it’s doing though, because instead of awaiting for the animation to finish it immediately calls the :Destroy() method.

The other issue is that calling :Destroy() before calling :Stop() on the animation track causes the animation to pause in place instead of being properly cleared.


Instead, you should:

  1. Create Animations from the animationIds list immediately

  2. When you create the characters: you should call the ::LoadAnimation() method and keep a record of all the related tracks for that humanoid

  3. You then need to modify the playAnimation(humanoid, animationId) method such that:

    • It plays the loaded animation track instead of a creating a new Animation and a new AnimationTrack every time

    • Keep a record of the currently playing animation, and check whether that animation has finished before trying to :Play() another one using the Ended event or the IsPlaying property; or in the case of the animation being looped, you should await for the DidLoop event to finish

  4. When you destroy the character, you should cleanup the associated animation tracks that relate to it

1 Like

I’m really not the greatest in scripting, and chatgpt was the only way i couldve been able to even get to this point in the script. I don’t know if i’d be able to implement everything you provided me by myself sadly