Hello!
I am trying to make an enemy approach the player if they are in range. I want the enemy to follow a preset path using waypoints and only deviate from this path when a player enters its range. I have set it up to print the nearest player and check if they are in range, but I am stuck on how to code the actual movement.
Ultimately, I want the enemy to leave its path, move toward the player, and then, after eliminating the player, return to its next waypoint and continue following the path to the end.
Any help or advice on how to achieve this would be greatly appreciated! If any additional information is needed, I’ll do my best to provide it.
This is my enemy script, which is a module script required by another script in ServerScriptService. In the script that requires the enemy module, I can create a simple wave layout and spawn enemies using enemyscript.Spawn(“(EnemyName)”, (Amount of Enemys I want), map.
-- Services --
local PS = game:GetService("PhysicsService")
local SSS = game:GetService("ServerScriptService")
local SS = game:GetService("ServerStorage")
local plrs = game:GetService("Players")
-- Locations --
EnemyStore = SS.EnemyStore
local enemy = {}
function enemy.Track(newEnemy, plrs)
local rootPart = newEnemy:WaitForChild("HumanoidRootPart")
local range = newEnemy:WaitForChild("Config"):WaitForChild("Range").Value
while newEnemy do
wait(1)
local nearestPlayer, nearestDistance
for _, player in pairs(plrs:GetPlayers()) do
local character = player.Character
local distance = player:DistanceFromCharacter(rootPart.Position)
if not character or distance > range or (nearestDistance and distance >= nearestDistance) then
continue
end
nearestDistance = distance
nearestPlayer = player
-- Scanning for nearby player
end
if nearestPlayer ~= nil and newEnemy:FindFirstChild(tostring(rootPart)) then
print("From", newEnemy.Name, "the nearest player is", nearestPlayer)
newEnemy:WaitForChild("Config"):WaitForChild("InRange").Value = true
-- Sees if there is a player, inputs the player then makes InRange True
elseif nearestPlayer == nil and newEnemy:FindFirstChild(tostring(rootPart)) then
newEnemy:WaitForChild("Config"):WaitForChild("InRange").Value = false
-- Sees if there is not a player, inputs the player then makes InRange False
elseif newEnemy:FindFirstChild(tostring(rootPart)) == false then
break
-- Sees if the enemy no longer exists, if so then it stops the checking process
end
end
end
function enemy.Move(enemy, map)
local humanoid = enemy:WaitForChild("Humanoid")
local waypoints = map.Waypoints
for waypoint=1, #waypoints:GetChildren() do
humanoid:MoveTo(waypoints[waypoint].Position)
humanoid.MoveToFinished:Wait()
end
enemy:Destroy()
end
function enemy.Spawn(name, quantity, map)
local enemyExists = SS.EnemyStore:FindFirstChild(name)
if enemyExists then
for i=1, quantity do
task.wait(0.5)
local newEnemy = enemyExists:Clone()
newEnemy.HumanoidRootPart.CFrame = map.Spawn.CFrame
newEnemy.Parent = workspace.Enemies
newEnemy.HumanoidRootPart:SetNetworkOwner(nil)
for i, object in ipairs(newEnemy:GetDescendants()) do
if object:IsA("BasePart") then
object.CollisionGroup = "Enemy"
end
end
coroutine.wrap(enemy.Move)(newEnemy, map)
coroutine.wrap(enemy.Track)(newEnemy, plrs)
end
else
warn("Enemy doesn't exists", name)
end
end
return enemy
If the code is recognizable its because I modified the Wave System from Gnomecode’s Tower Defense Tutorial.