--(( Modules ))--
local NPC = require(script.Parent)
local Utility = require(script.Parent.UtilityModule)
--(( Character ))--
local WalkerModel = game.ServerStorage.CharacterStorage.Walker
-- Module Table --
Walker = {}
Walker.__index = Walker
setmetatable(Walker, NPC)
--(( Zombie Constructor ))--
function Walker.new(spawnPoint)
--(( Setup ))--
local newWalker = NPC.new()
setmetatable(newWalker, Walker)
--(( Character ))--
newWalker.Character = WalkerModel:Clone()
newWalker.Humanoid = newWalker.Character.Humanoid
newWalker.Root = newWalker.Character.HumanoidRootPart
--(( Update Humanoid ))--
newWalker.Humanoid.WalkSpeed = 10
--(( Spawn ))--
newWalker.Character.Parent = game.Workspace
newWalker.Root.CFrame = spawnPoint
--(( Load Animations ))--
newWalker.Animations = Utility.getAnimations("Walker", newWalker.Humanoid.Animator)
--(( Walking Connections ))--
newWalker.Humanoid.Running:Connect(function(speed)
if speed > 0.5 then
newWalker.Animations["Walk"]:Play()
newWalker.Animations["Idle"]:Stop()
elseif speed <= 0 then
newWalker.Animations["Idle"]:Play()
newWalker.Animations["Walk"]:Stop()
end
end)
--(( Return Zombie ))--
return newWalker
end
--(( Module Table ))--
return Walker
The problem I face is that I do not know how to run code for an individual NPC; things like detecting nearby Players, chasing a Target, or performing some other action. Should I create a coroutine for each NPC to run these loops? Or is there an alternative method I should use?
When I make NPCs chase targets and perform actions I often use coroutines. I don’t really see any problem with it, either. I guess the only thing I can say is make sure the loop stops when the NPC dies.
I haven’t used coroutines at all before, so I’m a little unsure of the proper way to implement it. Would I simply make the coroutine in the Main Class and call resume on it from the handler? Or would this be something I should create outside of the classes?
Coroutines are certainly useful and will solve this problem. I however, just add all of the npcs to a list and loop through the list calling an :Update() function on all my npcs. It’s a bit trickier to yield since you can’t use wait without delaying the npcs behind it. I like it though because I always have direct control over when exactly each line will run relative to the other npcs.
I’m a little confused, I made the coroutine in the class like I mentioned, so that I could just reference the object to resume it, but it’s acting unexpectedly.
-- (( New Walker )) --
local myWalker1 = Walker.new(CFrame.new(0,20,8) * CFrame.Angles(0,0,0))
--(( Idle Zombie ))--
function UtilityTable.Idle(Zombie)
while true do
print("running!")
end
end
According to the API article “coroutine.create” only makes the object and it shouldn’t run until it’s resumed, yet the function runs anyways. Have I done something wrong?
Yes. You’re calling the function so it start it and will pass the returned value to coroutine.create. It takes just the variable name. Since you have parenthesis it thinks you want the returned value.
You pass parameters separated by comas in coroutine.resume.
You could add a variable to your NPC class that has a reference to the model.
Spawn NPC, create a bindable event inside that NPC with a function attached to it like so:
BindableEvent.Fired(Connect(function()
local myNPC = module.NPC.new(ARGS)
myNPC.model = BindableEvent.Parent
while BindableEvent.Parent ~= nil do
myNPC.DoLogic()
--May wanna put something like a wait() here or inside the logic function?
end
end)
You can keep running logic inside the NPC class until it’s parented to nil.
Destroying the model (and the BindableEvent inside) should eventually clean up the class and remove it from memory if I’m correct.