Trying to change animations played when in certain area

I’m trying to change the run & walk animations when a player is in a certain area.

I’ve tried lots of approaches of similar functions I’ve found on here across the past week but I’m stumped and keep bashing my head into layers of “knowledge lacking”!

So… I’ve tried Scripts & LocalScripts in ServerScriptService, StarterCharacterScript, and in the workspace.Part
I’ve tried local function onCharacterAdded(character) … area.Touched:Connect(function(…) … local function onTouch(part) … cloning animations from ServerStorage …

Here’s my latest attempt tweaked from a working change animation when character is added script in ServerScriptStorage.
I might have gotten closer with some previous attempts but I have a gaggle of disabled scripts ugly-crying throughout the folders and I don’t want to get my socks wet.

local Players = game:GetService("Players")
local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()

local area = workspace.Zone.area

local function onTouched(area)
	-- Get animator on humanoid
	local humanoid = character:WaitForChild("Humanoid")
	local animator = humanoid:WaitForChild("Animator")

	-- Stop all animation tracks
	for _, playingTrack in animator:GetPlayingAnimationTracks() do
		playingTrack:Stop(0)
	end

	local animateScript = character:WaitForChild("Animate")
	animateScript.run.RunAnim.AnimationId = "rbxassetid://16002698111"
	animateScript.walk.WalkAnim.AnimationId = "rbxassetid://16002698111"
end

area.Touched:Connect(onTouched)
1 Like

Uhh I don’t think u need to get the player service. I think it is better if u add a parameter to the function when u call it by the touched event with the same name as the function you created. After that, you can use that parameter to detect whether the player is walking through that area. If so, then you will change the animation

1 Like

Thanks! :slight_smile: I thought I needed to get the Players service so I could use LocalPlayer and character, and thus the Animate scripts so they can be changed.

So you think something more like this? Maybe with a debounce and TouchEnded to swap back after they leave?

I feel like once I understand why this isn’t working I could change it to a Region3, just depends on what’ll run smoother.

How would you define the variable “character” here?

-- define character somewhere somehow

local area = workspace.Zone.area

local function playerInArea()
	local humanoid = character:WaitForChild("Humanoid")
	local animator = humanoid:WaitForChild("Animator")

	for _, playingTrack in animator:GetPlayingAnimationTracks() do
		playingTrack:Stop(0)
	end

	local animateScript = character:WaitForChild("Animate")
	animateScript.run.RunAnim.AnimationId = "rbxassetid://16002698111"
	animateScript.walk.WalkAnim.AnimationId = "rbxassetid://16002698111"
end

area.Touched:Connect(playerInArea)
1 Like

I personally define the character by using the touched event. So how I do is when I do the touched event, I check whether the object that has hit is a player by using the hit parameter and then finding a child Humanoid. If so, this means that there is player in that zone and if so, your animation will change which look something like this

local area = game.Workspace:WaitForChild("Area")


area.Touched:Connect(function(hit)
	if hit.Parent:WaitForChild("Humanoid") then
		local humanoid = hit.Parent:WaitForChild("Humanoid")
		local character = hit.Parent
		-- Your code
	end
end)

The way I called the function is just my preferred way to do so as it can get the item that hit the object

1 Like

Alrighty! Was getting lots of hits of course - legs going this way, head going that way 'n all.
I tried adding a debounce but it just made it work intermittently.

Added an extra filter hit.Name == “HumanoidRootPart” and now it’s working much better.

  • 18:27:43.297 touched HumanoidRootPart - Server - ServScriSkatev4:4*
  • 18:28:03.816 ended HumanoidRootPart - Server - ServScriSkatev4:19*
  • 18:28:10.366 touched HumanoidRootPart - Server - ServScriSkatev4:4*
  • 18:28:12.932 ended HumanoidRootPart - Server - ServScriSkatev4:19*

Script’s in ServerScriptServices

local area = game.Workspace.Zone:WaitForChild("Area")

area.Touched:Connect(function(hit)
	print("touched", hit.Name)
	if hit.Name == "HumanoidRootPart" and hit.Parent:WaitForChild("Humanoid") then
		local humanoid = hit.Parent:WaitForChild("Humanoid")
		local character = hit.Parent
		local animator = humanoid:WaitForChild("Animator")
		for _, playingTrack in animator:GetPlayingAnimationTracks() do
			playingTrack:Stop(0)
		end
		local animateScript = character:WaitForChild("Animate")
		animateScript.run.RunAnim.AnimationId = "rbxassetid://16002698111"
		animateScript.walk.WalkAnim.AnimationId = "rbxassetid://16002698111"
	end
end)

area.TouchEnded:Connect(function(onEnd)
	print("ended", onEnd.Name)
	if onEnd.Name == "HumanoidRootPart" and onEnd.Parent:WaitForChild("Humanoid") then
		local humanoid = onEnd.Parent:WaitForChild("Humanoid")
		local character = onEnd.Parent
		local animator = humanoid:WaitForChild("Animator")
		for _, playingTrack in animator:GetPlayingAnimationTracks() do
			playingTrack:Stop(0)
		end
		local animateScript = character:WaitForChild("Animate")
		animateScript.run.RunAnim.AnimationId = "rbxassetid://913376220" -- default
		animateScript.walk.WalkAnim.AnimationId = "rbxassetid://913402848" -- default
	end
end)

If I decide to change it to Region3 I’ll pop back in with another script.

Another approach from @tralalah works too, as below.

(only issue I have now is that the animation doesn’t change until the player stops walking/running)

Woot! I figured out how to make the animation change while still getting input! Updated the script below.

Link to devforum post
A ServerStorage folder with all the contents of the Animate folder
A ServerStorage folder with all the contents of the Animate folder WITH any animation changes
A Script in ServerScriptService as below to swap them out

local area = workspace.Zone.Area
-- Area is a part that covers the whole area where animation is to occur, tall enough
-- so jumping doesn't cause TouchEnded. Transparency 1 and CanCollide false.

local defaultAnimsFolder = game:GetService("ServerStorage").AnimDefault
local newAnimsFolder = game:GetService("ServerStorage").AnimNew

area.Touched:Connect(function(hit)
	if hit.Name == "HumanoidRootPart" and hit.Parent:WaitForChild("Humanoid") then
		local humanoid = hit.Parent:WaitForChild("Humanoid")
		local animate = hit.Parent:WaitForChild("Animate")
		for _, animateFolderKids in pairs(animate:GetChildren()) do
			animateFolderKids:Destroy()
		end
		for _, newAnims in pairs(newAnimsFolder:GetChildren()) do
			local newStuff = newAnims:Clone()
			newStuff.Parent = animate
		end
		local animator = humanoid:WaitForChild("Animator")
		for _, playingTrack in animator:GetPlayingAnimationTracks() do
			playingTrack:Stop(1)
		end
		humanoid.WalkSpeed = 20
	end
end)

area.TouchEnded:Connect(function(hit)
	if hit.Name == "HumanoidRootPart" and hit.Parent:WaitForChild("Humanoid") then
		local humanoid = hit.Parent:WaitForChild("Humanoid")
		local animate = hit.Parent:WaitForChild("Animate")
		for _, animateFolderKids in pairs(animate:GetChildren()) do
			animateFolderKids:Destroy()
		end
		for _, newA in pairs(defaultAnimsFolder:GetChildren()) do
			local newStuff = newA:Clone()
			newStuff.Parent = animate
		end
		local animator = humanoid:WaitForChild("Animator")
		for _, playingTrack in animator:GetPlayingAnimationTracks() do
			playingTrack:Stop(1)
		end
		humanoid.WalkSpeed = 16
	end
end)
1 Like

Alrighty, I’ve been working hard hyperfocusing on this somewhat intensely.

I’ve just made this Script (in ServerScriptStorage) execute when a RemoteEvent (in ReplicatedStorage) is fired by a LocalScript (in StarterCharacter).

I ran into issues when I wanted to expand and complicate the area for the Touch event. Even combining the parts into a union I was getting TouchEnded events when the player was still in the “zone”.

Lemme try to summarise what I did and explain (I’m no pro, so sorry if terminology is incorrect)


Put a RemoteEvent in ReplicatedStorage, I renamed it RemEventFloor


LocalScript in StarterCharacter to change the movement sound effects
I used this guide by Itz_FloppyFish on youtube, they made the code able to be copied from the description (very helpful!).

--- added these variables above the function
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChild("RemEventFloor")

function updateFootstepsSound()
	local FloorMaterial = Humanoid.FloorMaterial
	-- after the variable for the FloorMaterial in the function I fired the Enum to the RemoteEvent
	remoteEvent:FireServer(FloorMaterial)

Script in ServerScriptStorage to swap out the animations in Humanoid.Animate
I had to change this code a fair bit from what I had above. There are lots of similarities and lots of differences so I’ll put the whole script below.

-- Again, added variables for the RemoteEvent at the top
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChild("RemEventFloor")

local defaultAnimsFolder = game:GetService("ServerStorage").AnimDefault
local newAnimsFolder = game:GetService("ServerStorage").AnimNew

-- Instead of Touched and TouchEnded functions I could use one function
-- connected to the RemoteEvent and the other arguments passed to it
-- by the LocalScript. I had to change how we got the Humanoid because
-- I no longer had that Touched event. The event handler on the server
-- always sends through the Player parameter first so...

local function onFloorMaterialChange(Player, FloorMaterial)
	local character = Player.Character -- (Player from RemoteEvent)
	local humanoid = character:WaitForChild("Humanoid")
	local animate = character:WaitForChild("Animate")

	-- if the FloorMaterial is ice
	if FloorMaterial == Enum.Material.Ice then -- (FloorMaterial from RemoteEvent)
		-- for all the animations in the Humanoid's Animate folder
		for _, animateFolderKids in pairs(animate:GetChildren()) do
			-- destroy them
			animateFolderKids:Destroy()
		end
		-- for all the new animations backed up in ServerStorage
		for _, newAnims in pairs(newAnimsFolder:GetChildren()) do
			-- clone them
			local newStuff = newAnims:Clone()
			-- and put them into the Humanoids' Animate folder 
			newStuff.Parent = animate
		end
		-- stop playing the current track so the cloned one can start
		local animator = humanoid:WaitForChild("Animator")
		for _, playingTrack in animator:GetPlayingAnimationTracks() do
			playingTrack:Stop(1)
		end
		-- increase the speed
		humanoid.WalkSpeed = 22
	-- if the above conditions aren't met put defaults back into Animate
	else
		for _, animateFolderKids in pairs(animate:GetChildren()) do
			animateFolderKids:Destroy()
		end
		for _, newA in pairs(defaultAnimsFolder:GetChildren()) do
			local newStuff = newA:Clone()
			newStuff.Parent = animate
		end
		local animator = humanoid:WaitForChild("Animator")
		for _, playingTrack in animator:GetPlayingAnimationTracks() do
			playingTrack:Stop(1)
		end
		humanoid.WalkSpeed = 16
	end
end

-- Connect the RemoteEvent to the above function
remoteEvent.OnServerEvent:Connect(onFloorMaterialChange)

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.