Play Button Doesn't Work After Changing Character

Hello,
The play button I created basically just teleports the players character to the start line in the Map Folder. This works only if I don’t change my character before pressing play. There are no errors but the button just doesn’t do anything when I click on it. All the other buttons work though.
I’ve tried changing the new characters name after swapping because I thought that was the problem but it still didn’t work. Thanks for any suggestions. Btw the player is changed during the gameplay so I don’t think StarterCharacter is an issue.

Module Script

local characterModify = {}
	

	function moveScripts(char1, char2)
		for _, v in char1:GetChildren() do
			if v:IsA("Script") or v:IsA("LocalScript") then
				v:Clone().Parent = char2
			end
		end
	end

	function characterModify.changeCharacter(player, model)
		local clonedChar = model:Clone()
		
		clonedChar:SetPrimaryPartCFrame(player.Character.PrimaryPart.CFrame)
		
		moveScripts(player.Character, clonedChar)
		
		clonedChar.Name = player.Name
		player.Character = clonedChar
		player.Character.Parent = workspace

	end

return characterModify

First Portion of the Main Loop Script


while true do
	task.wait()
	if table.maxn(playersTable) >= 0 then
		for _, v in playersTable do
			if v then
				for _, part in v:GetChildren() do
					v.Humanoid.WalkSpeed = 0
					v.HumanoidRootPart.CFrame = workspace.Map["Starting Line"].CFrame	-- Teleport To Start Line
					v.Humanoid.WalkSpeed = 0
				end
				
				
				for i = 3, 0, -1 do -- Count Down
					task.wait(1)
					remoteEvent:FireAllClients("Race Starts in "..tostring(i))
				end
				-- Game Starts Here
				
				inPlayBool = true
				
				workspace.Map["Finish Line"].Touched:Connect(function(hit)
					print("touched")
					if hit.Parent:FindFirstChild("Humanoid") then
						stopWatch:FireClient(game.Players:GetPlayerFromCharacter(hit.Parent))

						if not hit.Parent:FindFirstChild("Finished") then
							local finished = Instance.new("BoolValue", hit.Parent)
							finished.Name = "Finished"		
							table.insert(finishedPlayersTable, hit.Parent)
							table.insert(finishedTimesTable, tick()-startTime)
							print(finishedPlayersTable)
							print(finishedTimesTable)
						end
					end
				end)
				if not running then
					table.clear(finishedPlayersTable)
					table.clear(finishedTimesTable)
					startTime = tick()
					running = true
					print(startTime)
				end	
				if v:FindFirstChild("Finished") then
					v:FindFirstChild("Finished"):Destroy()
				end
				v.Humanoid.WalkSpeed = 75
				game.ReplicatedStorage.StartStopWatch:FireAllClients()
				for i = roundLength, 0, -1 do -- Count Down
					task.wait(1)
					remoteEvent:FireAllClients(formatScript.convertToMinutesAndSeconds(i))
				end

Changing Player

game.ReplicatedStorage.EquipPlayer.OnServerEvent:Connect(function(plr, characterName)
	for i, v in database:GetAsync(plr.UserId) do
		if v == characterName then
			playerModifier.changeCharacter(plr, game.ReplicatedStorage.Characters:FindFirstChild(characterName))
		end
	end
end)
2 Likes

Here’s how you can fix that in the teleportation logic:

for _, v in playersTable do
    if v then
        local character = game.Players:GetPlayerFromCharacter(v).Character or v -- Get the updated character

        -- Ensure we're working with the new character after swap
        if character then
            character.Humanoid.WalkSpeed = 0
            character.HumanoidRootPart.CFrame = workspace.Map["Starting Line"].CFrame -- Teleport to Start Line
            character.Humanoid.WalkSpeed = 0
        end
    end
end

Ensure that the cloned character has all the necessary parts (such as HumanoidRootPart and Humanoid) before assigning it as player.Character.

function characterModify.changeCharacter(player, model)
    local clonedChar = model:Clone()
    
    -- Ensure the cloned character has all necessary parts
    if clonedChar:FindFirstChild("HumanoidRootPart") and clonedChar:FindFirstChild("Humanoid") then
        clonedChar:SetPrimaryPartCFrame(player.Character.PrimaryPart.CFrame)
        moveScripts(player.Character, clonedChar)
        
        clonedChar.Name = player.Name
        player.Character = clonedChar
        clonedChar.Parent = workspace
    else
        warn("Cloned character is missing required parts!")
    end
end

When the character is changed, ensure that all properties (like WalkSpeed) are reapplied to the new character model.

function characterModify.changeCharacter(player, model)
    local clonedChar = model:Clone()
    if clonedChar:FindFirstChild("HumanoidRootPart") and clonedChar:FindFirstChild("Humanoid") then
        clonedChar:SetPrimaryPartCFrame(player.Character.PrimaryPart.CFrame)
        moveScripts(player.Character, clonedChar)
        
        clonedChar.Name = player.Name
        player.Character = clonedChar
        clonedChar.Parent = workspace

        -- Reapply necessary properties (WalkSpeed, etc.)
        clonedChar.Humanoid.WalkSpeed = 0 -- Ensure the new character can't move until game starts
    else
        warn("Cloned character is missing required parts!")
    end
end

After modifying the character, ensure the new character reference is passed correctly in all relevant places.

game.ReplicatedStorage.EquipPlayer.OnServerEvent:Connect(function(plr, characterName)
    for i, v in database:GetAsync(plr.UserId) do
        if v == characterName then
            -- Change character and ensure it's updated
            playerModifier.changeCharacter(plr, game.ReplicatedStorage.Characters:FindFirstChild(characterName))

            -- Optionally: Reapply any necessary configurations or properties to the new character
            local newCharacter = plr.Character
            if newCharacter:FindFirstChild("Humanoid") then
                newCharacter.Humanoid.WalkSpeed = 0 -- Reapply WalkSpeed
            end
        end
    end
end)
2 Likes

I’m still getting an infinite yield warning now on each part of the player for all the scripts imported to the player and a humanoidrootpart not found in one of them

Can you screenshot or show which lines?

Module

-- Module Script (characterModify)
local characterModify = {}

function moveScripts(char1, char2)
    for _, v in char1:GetChildren() do
        if v:IsA("Script") or v:IsA("LocalScript") then
            v:Clone().Parent = char2
        end
    end
end

function characterModify.changeCharacter(player, model)
    local clonedChar = model:Clone()
    
    -- Ensure HumanoidRootPart and Humanoid are present
    local humanoidRootPart = clonedChar:WaitForChild("HumanoidRootPart", 5)
    local humanoid = clonedChar:WaitForChild("Humanoid", 5)
    
    if not humanoidRootPart or not humanoid then
        warn("HumanoidRootPart or Humanoid is missing!")
        return
    end
    
    -- Set PrimaryPart and CFrame of the new character
    clonedChar.PrimaryPart = humanoidRootPart
    clonedChar:SetPrimaryPartCFrame(player.Character.PrimaryPart.CFrame)
    
    -- Move player scripts to the new character
    moveScripts(player.Character, clonedChar)
    
    -- Set new character
    clonedChar.Name = player.Name
    player.Character = clonedChar
    player.Character.Parent = workspace
end

return characterModify

Main Game Loop

-- Main Game Loop Script
while true do
    task.wait()
    
    if table.maxn(playersTable) >= 0 then
        for _, v in playersTable do
            if v then
                -- Ensure the character's HumanoidRootPart is present before teleporting
                if v:FindFirstChild("HumanoidRootPart") then
                    v.Humanoid.WalkSpeed = 0
                    v.HumanoidRootPart.CFrame = workspace.Map["Starting Line"].CFrame  -- Teleport to Start Line
                    v.Humanoid.WalkSpeed = 0
                else
                    warn(v.Name .. " is missing HumanoidRootPart")
                end

                -- Countdown for the race
                for i = 3, 0, -1 do
                    task.wait(1)
                    remoteEvent:FireAllClients("Race Starts in " .. tostring(i))
                end
                
                -- Game starts here
                inPlayBool = true
                
                -- Detect when players reach the finish line
                workspace.Map["Finish Line"].Touched:Connect(function(hit)
                    print("touched")
                    if hit.Parent:FindFirstChild("Humanoid") then
                        stopWatch:FireClient(game.Players:GetPlayerFromCharacter(hit.Parent))
                        
                        if not hit.Parent:FindFirstChild("Finished") then
                            local finished = Instance.new("BoolValue", hit.Parent)
                            finished.Name = "Finished"
                            table.insert(finishedPlayersTable, hit.Parent)
                            table.insert(finishedTimesTable, tick() - startTime)
                            print(finishedPlayersTable)
                            print(finishedTimesTable)
                        end
                    end
                end)

                -- Prepare for the next race
                if not running then
                    table.clear(finishedPlayersTable)
                    table.clear(finishedTimesTable)
                    startTime = tick()
                    running = true
                    print(startTime)
                end

                -- Cleanup the finished flag if it exists
                if v:FindFirstChild("Finished") then
                    v:FindFirstChild("Finished"):Destroy()
                end
                
                -- Set WalkSpeed to start moving
                v.Humanoid.WalkSpeed = 75
                game.ReplicatedStorage.StartStopWatch:FireAllClients()

                -- Countdown timer for the race
                for i = roundLength, 0, -1 do
                    task.wait(1)
                    remoteEvent:FireAllClients(formatScript.convertToMinutesAndSeconds(i))
                end
            end
        end
    end
end

Player Changing

-- Server Script: Character Change Logic
game.ReplicatedStorage.EquipPlayer.OnServerEvent:Connect(function(plr, characterName)
    local playerData = database:GetAsync(plr.UserId)
    
    for i, v in pairs(playerData) do
        if v == characterName then
            -- Modify the player character using the characterModify module
            local characterModel = game.ReplicatedStorage.Characters:FindFirstChild(characterName)
            if characterModel then
                characterModify.changeCharacter(plr, characterModel)
            else
                warn("Character model " .. characterName .. " not found in ReplicatedStorage!")
            end
        end
    end
end)

If this doesn’t work I need specific Output line references to look deeper.

1 Like

This may or may not be related to the issue because I wasn’t seeing these errors until updating the script

So referencing the scripts you posted for this thread, what are their names in your game?
In your output I see problems with scripts named DropDash, WallCling, and Animate

They’re local scripts in the startercharacterscripts I think when the players are switched it causes an error because the humanoidrootpart doesnt exist for a second

Paste all 3 scripts here I’ll try to solve it.

Drop Dash

local CAS = game:GetService("ContextActionService")



local function dropDash(actionName, inputState, inputObject)
	if actionName == "PressedShift" and inputState == Enum.UserInputState.Begin then
	script.Parent.HumanoidRootPart:ApplyImpulse(Vector3.new(0,-1000,0))
	end
end

local function castRay()
	-- The origin point of the ray
	local originPosition = script.Parent.HumanoidRootPart.Position
	-- The direction the ray is cast in
	local direction = script.Parent.HumanoidRootPart.CFrame.UpVector * -100
	-- The maximum distance of the ray
	local distance = 100

	-- Cast the ray and create a visualization of it
	local raycastParams = RaycastParams.new()
	raycastParams.FilterType = Enum.RaycastFilterType.Exclude; raycastParams.FilterDescendantsInstances = {game.Players.LocalPlayer.Character}; raycastParams.IgnoreWater = true
	local raycastResult = game.Workspace:Raycast(originPosition, direction * distance, raycastParams)
	if raycastResult then
		return raycastResult.Distance
	end
end


while true do
	task.wait()
	if castRay() >= 4 or nil then
	CAS:BindAction("PressedShift", dropDash, true, Enum.KeyCode.LeftShift, Enum.KeyCode.ButtonL2)
	else
		CAS:UnbindAction("PressedShift")
	end
end

Wall Cling

local USER_INPUT_SERVICE = game:GetService("UserInputService")
local RUN_SERVICE = game:GetService("RunService")

local Character = script.Parent
local RootPart = Character:WaitForChild("HumanoidRootPart")
local Humanoid = Character:WaitForChild("Humanoid")

local LastJump = tick()
local animation = Instance.new("Animation")
animation.AnimationId = "rbxassetid://120370480050502" -- Roblox dance emote

local animationTrack = Humanoid:LoadAnimation(animation)

local slideEffect = script.Parent.HumanoidRootPart.SlideEffect
slideEffect.Parent = game.Players.LocalPlayer.Character.HumanoidRootPart
slideEffect.Enabled = false


Humanoid.Touched:Connect(function(hit,touchpart)
	local ray = Ray.new(RootPart.Position, RootPart.CFrame.LookVector * 2.5)
	local part, point, normal = workspace:FindPartOnRay(ray, Character)

	if part and part:FindFirstChild("_Wall") and tick() - LastJump > 0.1 and touchpart.Name == "HumanoidRootPart" then
		RootPart.Anchored = true
		task.wait()
		RootPart.Anchored = false
		workspace.Gravity = 25
		Humanoid.WalkSpeed = 0
		RootPart.CFrame = CFrame.new(RootPart.Position, RootPart.Position + normal)
		animationTrack:Play()
		slideEffect.Enabled = true

		local jumped = false
		local begin = tick()

		spawn(function()
			USER_INPUT_SERVICE.JumpRequest:Wait()
			jumped = true
		end)

		repeat
			RUN_SERVICE.Heartbeat:Wait() 
		until jumped or tick() - begin > .85

		LastJump = tick()
		RootPart.Anchored = false

		if jumped then
			RootPart.Velocity = Vector3.new(40 * normal.X, 50 * normal.Y + 90, 40 * normal.Z)
			workspace.Gravity = 196.2
			Humanoid.WalkSpeed = 75
			animationTrack:Stop()
			slideEffect.Enabled = false
		else
			animationTrack:Stop()
			slideEffect.Enabled = false
			RootPart.Velocity = Vector3.new()
			workspace.Gravity = 196.2
			Humanoid.WalkSpeed = 75
		end
	end
end)

Animate

-- humanoidAnimatePlayEmote.lua

local Figure = script.Parent
local Torso = Figure:WaitForChild("Torso")
local RightShoulder = Torso:WaitForChild("Right Shoulder")
local LeftShoulder = Torso:WaitForChild("Left Shoulder")
local RightHip = Torso:WaitForChild("Right Hip")
local LeftHip = Torso:WaitForChild("Left Hip")
local Neck = Torso:WaitForChild("Neck")
local Humanoid = Figure:WaitForChild("Humanoid")
local pose = "Standing"

local EMOTE_TRANSITION_TIME = 0.1

local userAnimateScaleRunSuccess, userAnimateScaleRunValue = pcall(function() return UserSettings():IsUserFeatureEnabled("UserAnimateScaleRun") end)
local userAnimateScaleRun = userAnimateScaleRunSuccess and userAnimateScaleRunValue

local function getRigScale()
	if userAnimateScaleRun then
		return Figure:GetScale()
	else
		return 1
	end
end

local currentAnim = ""
local currentAnimInstance = nil
local currentAnimTrack = nil
local currentAnimKeyframeHandler = nil
local currentAnimSpeed = 1.0
local animTable = {}
local animNames = { 
	idle = 	{	
				{ id = "http://www.roblox.com/asset/?id=180435571", weight = 9 },
				{ id = "http://www.roblox.com/asset/?id=180435792", weight = 1 }
			},
	walk = 	{ 	
		{ id = "rbxassetid://114009241914984", weight = 10 } 
			}, 
	run = 	{
		{ id = "rbxassetid://114009241914984", weight = 10 } 
			}, 
	jump = 	{
		{ id = "rbxassetid://78382364526757", weight = 10 } 
			}, 
	fall = 	{
				{ id = "http://www.roblox.com/asset/?id=180436148", weight = 10 } 
			}, 
	climb = {
				{ id = "http://www.roblox.com/asset/?id=180436334", weight = 10 } 
			}, 
	sit = 	{
				{ id = "http://www.roblox.com/asset/?id=178130996", weight = 10 } 
			},	
	toolnone = {
				{ id = "http://www.roblox.com/asset/?id=182393478", weight = 10 } 
			},
	toolslash = {
				{ id = "http://www.roblox.com/asset/?id=129967390", weight = 10 } 
--				{ id = "slash.xml", weight = 10 } 
			},
	toollunge = {
				{ id = "http://www.roblox.com/asset/?id=129967478", weight = 10 } 
			},
	wave = {
				{ id = "http://www.roblox.com/asset/?id=128777973", weight = 10 } 
			},
	point = {
				{ id = "http://www.roblox.com/asset/?id=128853357", weight = 10 } 
			},
	dance1 = {
				{ id = "http://www.roblox.com/asset/?id=182435998", weight = 10 }, 
				{ id = "http://www.roblox.com/asset/?id=182491037", weight = 10 }, 
				{ id = "http://www.roblox.com/asset/?id=182491065", weight = 10 } 
			},
	dance2 = {
				{ id = "http://www.roblox.com/asset/?id=182436842", weight = 10 }, 
				{ id = "http://www.roblox.com/asset/?id=182491248", weight = 10 }, 
				{ id = "http://www.roblox.com/asset/?id=182491277", weight = 10 } 
			},
	dance3 = {
				{ id = "http://www.roblox.com/asset/?id=182436935", weight = 10 }, 
				{ id = "http://www.roblox.com/asset/?id=182491368", weight = 10 }, 
				{ id = "http://www.roblox.com/asset/?id=182491423", weight = 10 } 
			},
	laugh = {
				{ id = "http://www.roblox.com/asset/?id=129423131", weight = 10 } 
			},
	cheer = {
				{ id = "http://www.roblox.com/asset/?id=129423030", weight = 10 } 
			},
}
local dances = {"dance1", "dance2", "dance3"}

-- 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, dance1 = true, dance2 = true, dance3 = true, laugh = false, cheer = false}

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 = {}

	-- check for config values
	local config = script:FindFirstChild(name)
	if (config ~= nil) then
--		print("Loading anims " .. name)
		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
	--			print(name .. " [" .. idx .. "] " .. animTable[name][idx].anim.AnimationId .. " (" .. 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)

-- Clear any existing animation tracks
-- Fixes issue with characters that are moved in and out of the Workspace accumulating tracks
local animator = if Humanoid then Humanoid:FindFirstChildOfClass("Animator") else nil
if animator then
	local animTracks = animator:GetPlayingAnimationTracks()
	for i,track in ipairs(animTracks) do
		track:Stop(0)
		track:Destroy()
	end
end


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.3

local toolTransitionTime = 0.1
local fallTransitionTime = 0.3
local jumpMaxLimbVelocity = 0.75

-- 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
	return oldAnim
end

function setAnimationSpeed(speed)
	if speed ~= currentAnimSpeed then
		currentAnimSpeed = speed
		currentAnimTrack:AdjustSpeed(currentAnimSpeed)
	end
end

function keyFrameReachedFunc(frameName)
	if (frameName == "End") then

		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.0, Humanoid)
		setAnimationSpeed(animSpeed)
	end
end

-- Preload animations
function playAnimation(animName, transitionTime, humanoid) 
		
	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
--		print(animName .. " " .. idx .. " [" .. origRoll .. "]")
	local anim = animTable[animName][idx].anim

	-- switch animation		
	if (anim ~= currentAnimInstance) then
		
		if (currentAnimTrack ~= nil) then
			currentAnimTrack:Stop(transitionTime)
			currentAnimTrack: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)
		
	end

end

-------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------

local toolAnimName = ""
local toolAnimTrack = nil
local toolAnimInstance = nil
local currentToolAnimKeyframeHandler = nil

function toolKeyFrameReachedFunc(frameName)
	if (frameName == "End") then
--		print("Keyframe : ".. frameName)	
		playToolAnimation(toolAnimName, 0.0, Humanoid)
	end
end


function playToolAnimation(animName, transitionTime, humanoid, priority)	 
		
		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
--		print(animName .. " * " .. idx .. " [" .. origRoll .. "]")
		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

-------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------


function onRunning(speed)
	speed /= getRigScale()
	
	if speed > 0.01 then
		playAnimation("walk", 0.1, Humanoid)
		if currentAnimInstance and currentAnimInstance.AnimationId == "http://www.roblox.com/asset/?id=180426354" then
			setAnimationSpeed(speed / 14.5)
		end
		pose = "Running"
	else
		if emoteNames[currentAnim] == nil then
			playAnimation("idle", 0.1, 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)
	speed /= getRigScale()
	
	playAnimation("climb", 0.1, Humanoid)
	setAnimationSpeed(speed / 12.0)
	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 > 0 then
		pose = "Running"
	else
		pose = "Standing"
	end
end

function getTool()	
	for _, kid in ipairs(Figure:GetChildren()) do
		if kid.className == "Tool" then return kid end
	end
	return nil
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

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 moveSit()
	RightShoulder.MaxVelocity = 0.15
	LeftShoulder.MaxVelocity = 0.15
	RightShoulder:SetDesiredAngle(3.14 /2)
	LeftShoulder:SetDesiredAngle(-3.14 /2)
	RightHip:SetDesiredAngle(3.14 /2)
	LeftHip:SetDesiredAngle(-3.14 /2)
end

local lastTick = 0

function move(time)
	local amplitude = 1
	local frequency = 1
  	local deltaTime = time - lastTick
  	lastTick = time

	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.1, Humanoid)
	elseif (pose == "Dead" or pose == "GettingUp" or pose == "FallingDown" or pose == "Seated" or pose == "PlatformStanding") then
--		print("Wha " .. pose)
		stopAllAnimations()
		amplitude = 0.1
		frequency = 1
		setAngles = true
	end

	if (setAngles) then
		local desiredAngle = amplitude * math.sin(time * frequency)

		RightShoulder:SetDesiredAngle(desiredAngle + climbFudge)
		LeftShoulder:SetDesiredAngle(desiredAngle - climbFudge)
		RightHip:SetDesiredAngle(-desiredAngle)
		LeftHip:SetDesiredAngle(-desiredAngle)
	end

	-- Tool Animation handling
	local tool = getTool()
	if tool and tool:FindFirstChild("Handle") then
	
		local animStringValueObject = getToolAnim(tool)

		if animStringValueObject then
			toolAnim = animStringValueObject.Value
			-- message recieved, delete StringValue
			animStringValueObject.Parent = nil
			toolAnimTime = time + .3
		end

		if time > 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 msg == "/e dance" then
		emote = dances[math.random(1, #dances)]
	elseif (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)

-- emote bindable hook
script:WaitForChild("PlayEmote").OnInvoke = function(emote)
	-- Only play emotes when idling
	if pose ~= "Standing" then
		return
	end
	if emoteNames[emote] ~= nil then
		-- Default emotes
		playAnimation(emote, EMOTE_TRANSITION_TIME, Humanoid)

		return true, currentAnimTrack
	end

	-- Return false to indicate that the emote could not be played
	return false
end
-- main program

-- initialize to idle
playAnimation("idle", 0.1, Humanoid)
pose = "Standing"

while Figure.Parent ~= nil do
	local _, time = wait(0.1)
	move(time)
end

I thought changing the character would be so much easier considering lots of games have it lol

Drop Dash

local USER_INPUT_SERVICE = game:GetService("UserInputService")
local RUN_SERVICE = game:GetService("RunService")

local Character = script.Parent

-- Directly use HumanoidRootPart for both R6 and R15 rigs
local RootPart = Character:WaitForChild("HumanoidRootPart")
local Humanoid = Character:WaitForChild("Humanoid")

local LastJump = tick()
local animation = Instance.new("Animation")
animation.AnimationId = "rbxassetid://120370480050502"

local animationTrack = Humanoid:LoadAnimation(animation)

-- Check if SlideEffect exists
local slideEffect = RootPart:FindFirstChild("SlideEffect")
if not slideEffect then
    warn("SlideEffect not found on HumanoidRootPart!")
    return
end
slideEffect.Parent = game.Players.LocalPlayer.Character.HumanoidRootPart
slideEffect.Enabled = false

Humanoid.Touched:Connect(function(hit, touchpart)
    local ray = Ray.new(RootPart.Position, RootPart.CFrame.LookVector * 2.5)
    local part, point, normal = workspace:FindPartOnRay(ray, Character)

    if part and part:FindFirstChild("_Wall") and tick() - LastJump > 0.1 and touchpart.Name == "HumanoidRootPart" then
        RootPart.Anchored = true
        task.wait()
        RootPart.Anchored = false
        workspace.Gravity = 25
        Humanoid.WalkSpeed = 0
        RootPart.CFrame = CFrame.new(RootPart.Position, RootPart.Position + normal)
        animationTrack:Play()
        slideEffect.Enabled = true

        local jumped = false
        local begin = tick()

        spawn(function()
            USER_INPUT_SERVICE.JumpRequest:Wait()
            jumped = true
        end)

        repeat
            RUN_SERVICE.Heartbeat:Wait() 
        until jumped or tick() - begin > .85

        LastJump = tick()
        RootPart.Anchored = false

        if jumped then
            RootPart.Velocity = Vector3.new(40 * normal.X, 50 * normal.Y + 90, 40 * normal.Z)
            workspace.Gravity = 196.2
            Humanoid.WalkSpeed = 75
            animationTrack:Stop()
            slideEffect.Enabled = false
        else
            animationTrack:Stop()
            slideEffect.Enabled = false
            RootPart.Velocity = Vector3.new()
            workspace.Gravity = 196.2
            Humanoid.WalkSpeed = 75
        end
    end
end)

Animate

local Figure = script.Parent
local Humanoid = Figure:WaitForChild("Humanoid")

-- Handles R6 and R15 differences
local Torso = Figure:FindFirstChild("Torso") or Figure:FindFirstChild("UpperTorso")
local RightShoulder = Torso and Torso:FindFirstChild("Right Shoulder") or Figure:WaitForChild("RightUpperArm")
local LeftShoulder = Torso and Torso:FindFirstChild("Left Shoulder") or Figure:WaitForChild("LeftUpperArm")
local RightHip = Torso and Torso:FindFirstChild("Right Hip") or Figure:WaitForChild("RightUpperLeg")
local LeftHip = Torso and Torso:FindFirstChild("Left Hip") or Figure:WaitForChild("LeftUpperLeg")
local Neck = Torso and Torso:FindFirstChild("Neck") or Figure:WaitForChild("Neck")

local pose = "Standing"
local EMOTE_TRANSITION_TIME = 0.1

local currentAnim = ""
local currentAnimTrack = nil
local currentAnimSpeed = 1.0
local animTable = {}
local animNames = { 
    idle = { { id = "http://www.roblox.com/asset/?id=180435571", weight = 9 }, { id = "http://www.roblox.com/asset/?id=180435792", weight = 1 } },
    walk = { { id = "rbxassetid://114009241914984", weight = 10 } }, 
    run = { { id = "rbxassetid://114009241914984", weight = 10 } }, 
    jump = { { id = "rbxassetid://78382364526757", weight = 10 } },
    fall = { { id = "http://www.roblox.com/asset/?id=180436148", weight = 10 } }, 
    climb = { { id = "http://www.roblox.com/asset/?id=180436334", weight = 10 } }, 
    sit = { { id = "http://www.roblox.com/asset/?id=178130996", weight = 10 } },
    toolnone = { { id = "http://www.roblox.com/asset/?id=182393478", weight = 10 } }
}

-- Setup animation objects
local function configureAnimationSet(name, fileList)
    animTable[name] = {}
    animTable[name].count = 0
    animTable[name].totalWeight = 0

    local idx = 1
    for _, anim in pairs(fileList) do
        animTable[name][idx] = { anim = Instance.new("Animation"), weight = anim.weight }
        animTable[name][idx].anim.AnimationId = anim.id
        animTable[name].count = animTable[name].count + 1
        animTable[name].totalWeight = animTable[name].totalWeight + anim.weight
        idx = idx + 1
    end
end

for name, fileList in pairs(animNames) do
    configureAnimationSet(name, fileList)
end

-- Functions to play and manage animations
local function playAnimation(animName, transitionTime, humanoid)
    local animSet = animTable[animName]
    if animSet then
        local roll = math.random(1, animSet.totalWeight)
        local idx = 1
        while roll > animSet[idx].weight do
            roll = roll - animSet[idx].weight
            idx = idx + 1
        end
        local anim = animSet[idx].anim

        if currentAnimTrack then
            currentAnimTrack:Stop(transitionTime)
            currentAnimTrack:Destroy()
        end

        currentAnimTrack = humanoid:LoadAnimation(anim)
        currentAnimTrack.Priority = Enum.AnimationPriority.Core
        currentAnimTrack:Play(transitionTime)
    end
end

-- Stop all animations
local function stopAllAnimations()
    if currentAnimTrack then
        currentAnimTrack:Stop()
        currentAnimTrack:Destroy()
        currentAnimTrack = nil
    end
end

-- Event listeners for humanoid actions
Humanoid.Died:Connect(function() pose = "Dead" stopAllAnimations() end)
Humanoid.Running:Connect(function(speed) 
    if speed > 0.01 then
        playAnimation("walk", 0.1, Humanoid)
        pose = "Running"
    else
        playAnimation("idle", 0.1, Humanoid)
        pose = "Standing"
    end
end)
Humanoid.Jumping:Connect(function() playAnimation("jump", 0.1, Humanoid) pose = "Jumping" end)
Humanoid.FreeFalling:Connect(function() playAnimation("fall", 0.1, Humanoid) pose = "FreeFalling" end)

-- Play default idle animation at startup
playAnimation("idle", 0.1, Humanoid)

while Figure.Parent do
    task.wait(0.1)
end
1 Like

I’m still getting the same warnings :expressionless: i may just have to find another way to change the character. Thanks though

I actually was able to figure out the problem turns out when you change the character it counts as the player respawning so turning on ResetOnSpawn for the GUI makes it work correctly. Thanks for your help