Playing an animation into an NPC locally

Hey there everyone!

I’ve been having a few issues with a script recently for an upcoming game I’m working on. I’ve been trying to get NPCs loaded locally into the game, so that the player can only see actions that they do with them. I’ve had no issue loading them in, and getting them found by the module script which is fired by a local script once the player joins the game.

However, I cannot seem to be able to animate the NPCs locally once the map is spawned and locally placed for the player.

There aren’t any errors coming up, and everytime I print something, it always prints. I’ve tried almost everything I could think of, from re-uploading the idle animation, to placing an animator inside of the humanoid.

Basically, all of the modules are located inside of ReplicatedStorage, including the MapChunks (So that the local scripts have access to them).

image

Then off in StarterGui, there is a single local script that starts the chain of scripts with this code:

Startup
local repstorage = game:GetService("ReplicatedStorage")

local _p = game.Players.LocalPlayer

repeat wait() until _p.Character -- wait until character loads in

local Chunkmodule = require(repstorage.Plugins:FindFirstChild("Chunk"))
Chunkmodule.OnLoadChunk("_chunktest")

image

Then, back into ReplicatedStorage where the “Chunk” module is located, where it loads in the chunk locally for the player. Along with this code:

ChunkModule
local chunkmodule = {}

local chunkfolder = game.ServerStorage:FindFirstChild("MapChunks")

local camera = game.Workspace.CurrentCamera

local npcmodule = require(script.Parent.NPC)

chunkmodule.OnLoadChunk = function(chunk)
	local map = chunkfolder:FindFirstChild(chunk)
	if not map then error(chunk.." not found") return end -- for debug
	
	print('map found')
	
	npcmodule.FindNPCs(map)	
	npcmodule.AnimateNPCs(map)
	
	map:Clone().Parent = camera -- now load the map into the camera for local use
end

chunkmodule.UnLoadChunk = function(chunk)
	local cam = game.Workspace.CurrentCamera
	for i,v in pairs(cam:GetChildren()) do
		if v.Name == chunk then
			v:Destroy()
		end
	end
end


return chunkmodule

Once the chunk module finds the map, the NPCs are then found, then animated through the NPCModule:

FullNPCModule
local NPCModule = {}

function AddTag(NPC)
	local tag = Instance.new("StringValue", NPC)
	tag.Name = "#NPC"
end

local assetmodule = require(script.Parent.Parent.Data.Assets)

local vwalk, vpoint, vwave

NPCModule.AnimateNPCs = function(loadedchunk)
	for i,v in pairs(loadedchunk:GetChildren()) do
		if v:FindFirstChild("#NPC") and not v:FindFirstChild("NoAnimation") then
			print(v.Name)
			local vhum = v:FindFirstChild("Humanoid")
			if not vhum then error(v.Name.." has no Humanoid") return end
			local va = Instance.new("Animator", vhum)
			vhum.DisplayDistanceType = Enum.HumanoidDisplayDistanceType.None
			local vidlean = Instance.new("Animation", vhum)
			vidlean.AnimationId = "rbxassetid://"..assetmodule.animationId.NPCIdle
			local vwalkan = Instance.new("Animation", vhum)
			vwalkan.AnimationId = "rbxassetid://"..assetmodule.animationId.NPCWalk	
			local vpointan = Instance.new("Animation")
			vpointan.AnimationId = "rbxassetid://"..assetmodule.animationId.NPCPoint
			local vwavean = Instance.new("Animation")	
			vwavean.AnimationId = "rbxassetid://"..assetmodule.animationId.NPCWave	
			local vidle = va:LoadAnimation(vidlean)
			vwalk = vhum:LoadAnimation(vwalkan)	
			vpoint = vhum:LoadAnimation(vpointan)
			vwave = vhum:LoadAnimation(vwavean)	
			vwalk:Play()	
			print('played')
		end
	end
end

NPCModule.FindNPCs = function(loadedchunk)
	local map = loadedchunk
	for i,v in pairs(map:GetChildren()) do
		if v:FindFirstChild("Humanoid") and v:FindFirstChild("HumanoidRootPart") then
			AddTag(v)
		elseif v:FindFirstChild("Humanoid") and not v:FindFirstChild("HumanoidRootPart") then -- these are just here to help with debugging
			error(v.Name.." does not have a HumanoidRootPart")	
		elseif not v:FindFirstChild("Humanoid") and v:FindFirstChild("HumanoidRootPart") then
			error(v.Name.." does not have a Humanoid")		
		end
	end
end

return NPCModule

That’s how the NPC is loaded through these scripts so far. Like said in the replies, I haven’t made the NPCs go through Workspace themselves without going into the camera, and will change a few minor things as well.

If this adds anything to it, the “chunk” model location is ReplicatedStorage, and it is pulled from RS after the NPCs go through animating.

I’ve looked at countless DevForum posts about similar issues, but none of them have helped this issue I’ve been having.

If anybody has any suggestions/solutions, they would be much appreciated! :slight_smile:

So i’m confused is your problem that the animations are being played sever wide or just not playing at all?

The animations are not being played at all, while I’m trying to play them locally.

Is the idle animation playing but not the others?

No animation is playing, even if I do animation:Play() for the other animations.

Output please (30 charssssssssssss)

@im_sams
thirty charassssssssss

Looks like vidle is the only one that plays did you mean to do that to also have other ones play?? (Sorry not familiar with animation scripts)

And is animation id in module I’m assuming is a module valid ?

The output is very weird to me, since the animation doesn’t seem to error in anyway, and anything that I place down under the :Play() is printed. I’ve even tried printing the assetid that it gets from the data module.

I’m not sure, but it may be something to do with it being moved to game.Workspace.CurrentCamera from ReplicatedStorage.

With answering your other question, vidle is the only one that is meant to play, the others are there just to be loaded in. Sorry for the confusion; should’ve specified in the post.

1 Like

Don’t put NPC models in the CurrentCamera, that’s a legacy method of making things local. Simply having the LocalScript copy the NPC over to the workspace should suffice well enough.

Also worth pointing out that you should stop using the parent argument of Instance.new.

1 Like

Thanks, I’ll try this and mark it as solution! :slight_smile:

It’s not really a solution so it shouldn’t be marked. It’s simply informing you that you’re using practices that are out of date and should look towards reviewing your code to turn those over. Things not confirmed to resolve your problem should not be marked as solutions.

I don’t know how you’re going about locally loading your NPCs, where this module is located nor where the script intended to use this ModuleScript are. The only kind of code that has been provided in this thread is the NPC animate script.

I’ll edit the main post and specify as much as I can so that people can get a better understanding overall before scrolling down to the replies, but I’ll locate where everything is here for people who were active in this thread.

Basically, all of the modules are located inside of ReplicatedStorage, including the MapChunks (So that the local scripts have access to them).

image

Then off in StarterGui, there is a single local script that starts the chain of scripts with this code:

Startup
local repstorage = game:GetService("ReplicatedStorage")

local _p = game.Players.LocalPlayer

repeat wait() until _p.Character -- wait until character loads in

local Chunkmodule = require(repstorage.Plugins:FindFirstChild("Chunk"))
Chunkmodule.OnLoadChunk("_chunktest")

image

Then, back into ReplicatedStorage where the “Chunk” module is located, where it loads in the chunk locally for the player. Along with this code:

ChunkModule
local chunkmodule = {}

local chunkfolder = game.ServerStorage:FindFirstChild("MapChunks")

local camera = game.Workspace.CurrentCamera

local npcmodule = require(script.Parent.NPC)

chunkmodule.OnLoadChunk = function(chunk)
	local map = chunkfolder:FindFirstChild(chunk)
	if not map then error(chunk.." not found") return end -- for debug
	
	print('map found')
	
	npcmodule.FindNPCs(map)	
	npcmodule.AnimateNPCs(map)
	
	map:Clone().Parent = camera -- now load the map into the camera for local use
end

chunkmodule.UnLoadChunk = function(chunk)
	local cam = game.Workspace.CurrentCamera
	for i,v in pairs(cam:GetChildren()) do
		if v.Name == chunk then
			v:Destroy()
		end
	end
end


return chunkmodule

Once the chunk module finds the map, the NPCs are then found, then animated through the above shown NPCModule, but I’ll show the full script here:

FullNPCModule
local NPCModule = {}

function AddTag(NPC)
	local tag = Instance.new("StringValue", NPC)
	tag.Name = "#NPC"
end

local assetmodule = require(script.Parent.Parent.Data.Assets)

local vwalk, vpoint, vwave

NPCModule.AnimateNPCs = function(loadedchunk)
	for i,v in pairs(loadedchunk:GetChildren()) do
		if v:FindFirstChild("#NPC") and not v:FindFirstChild("NoAnimation") then
			print(v.Name)
			local vhum = v:FindFirstChild("Humanoid")
			if not vhum then error(v.Name.." has no Humanoid") return end
			local va = Instance.new("Animator", vhum)
			vhum.DisplayDistanceType = Enum.HumanoidDisplayDistanceType.None
			local vidlean = Instance.new("Animation", vhum)
			vidlean.AnimationId = "rbxassetid://"..assetmodule.animationId.NPCIdle
			local vwalkan = Instance.new("Animation", vhum)
			vwalkan.AnimationId = "rbxassetid://"..assetmodule.animationId.NPCWalk	
			local vpointan = Instance.new("Animation")
			vpointan.AnimationId = "rbxassetid://"..assetmodule.animationId.NPCPoint
			local vwavean = Instance.new("Animation")	
			vwavean.AnimationId = "rbxassetid://"..assetmodule.animationId.NPCWave	
			local vidle = va:LoadAnimation(vidlean)
			vwalk = vhum:LoadAnimation(vwalkan)	
			vpoint = vhum:LoadAnimation(vpointan)
			vwave = vhum:LoadAnimation(vwavean)	
			vwalk:Play()	
			print('played')
		end
	end
end

NPCModule.FindNPCs = function(loadedchunk)
	local map = loadedchunk
	for i,v in pairs(map:GetChildren()) do
		if v:FindFirstChild("Humanoid") and v:FindFirstChild("HumanoidRootPart") then
			AddTag(v)
		elseif v:FindFirstChild("Humanoid") and not v:FindFirstChild("HumanoidRootPart") then -- these are just here to help with debugging
			error(v.Name.." does not have a HumanoidRootPart")	
		elseif not v:FindFirstChild("Humanoid") and v:FindFirstChild("HumanoidRootPart") then
			error(v.Name.." does not have a Humanoid")		
		end
	end
end

return NPCModule

That’s how the NPC is loaded through these scripts so far. Like said above, I haven’t made the NPCs go through Workspace themselves without going into the camera, and will change a few minor things as well.

I will update the main thread with all of this as well.

I have actually solved the issue by moving the NPC’s parent outside of the camera. Will follow this through my scripts from now on. Thanks for everybody’s help, I really appreciate this community! :slight_smile: