honestly, i’m not even sure where this came from and when this happened
i’m just playtesting my game and all of a sudden my enemies don’t play animations nor pathfind, they’re just… unanchored models
they play sounds, but not animations?
they also ignore the player, super weird
animate script (individual for each enemy):
local dService = game:GetService("Debris")
local enemy = script.Parent
local enemyHumanoid = enemy:WaitForChild("Humanoid")
local enemyRootPart = enemy:FindFirstChild("HumanoidRootPart")
local enemyAnimator = enemyHumanoid:FindFirstChild("Animator")
-- Folder of animations
local animationsFolder = enemy:WaitForChild("Animations")
-- Animations;
local idle = animationsFolder:WaitForChild("Idle")
local chase = animationsFolder:WaitForChild("Chase")
local death = animationsFolder:WaitForChild("Death")
local wander = animationsFolder:WaitForChild("Death")
-- Folder of sounds;
local soundsFolder = enemy:WaitForChild("Sounds")
-- Sounds;
local idleSound = soundsFolder:WaitForChild("IdleSound")
local deathSound = soundsFolder:WaitForChild("DeathSound")
-- Loaded animations;
local idleTrack = enemyAnimator:LoadAnimation(idle)
local chaseTrack = enemyAnimator:LoadAnimation(chase)
local deathTrack = enemyAnimator:LoadAnimation(death)
local wanderTrack = enemyAnimator:LoadAnimation(wander)
-- Connections;
local idleSoundFinishedConn = nil
-- Functions;
function HandleIdleSounds()
while enemyHumanoid.Health > 0 do
-- getting the current state of the enemy
local chasingAttribute: boolean = enemy:GetAttribute("Chasing")
local fleeingAttribute: boolean = enemy:GetAttribute("Fleeing")
local stunnedAttribute: boolean = enemy:GetAttribute("Stunned")
-- breaking the loop if any of those attributes are true
if chasingAttribute == true or fleeingAttribute == true or stunnedAttribute == true then
idleSound:Stop()
break
end
-- temporarily parent the sound to the root part to prevent hearing everywhere
idleSound.Parent = enemyRootPart
-- play the sound and create a random cooldown
idleSound:Play()
local randomCooldown = math.random(3,10)
idleSoundFinishedConn = idleSound.Ended:Connect(function()
task.wait(.1)
idleSound.Parent = soundsFolder
idleSoundFinishedConn:Disconnect()
end)
-- wait out the cooldown and loop
task.wait(randomCooldown)
end
end
function OnEnemyDied()
-- stop any on-going animation
for _, anim in enemyAnimator:GetPlayingAnimationTracks() do
anim:Stop()
end
-- get the death sound
local deathSound = soundsFolder.DeathSound
-- parent it to the root part to prevent hearing everywhere
deathSound.Parent = enemyRootPart
-- prepare the enemy for the death animation
-- and then play
enemyRootPart.Anchored = true
for _, limb: BasePart in enemy:GetDescendants() do
if not limb:IsA("BasePart") then continue end
limb.CanCollide = false
end
deathTrack:Play()
-- parent the enemy to the workspace so the game no longer tracks it
-- and also put the enemy into a destroy queue
enemy.Parent = workspace
dService:AddItem(enemy, 10)
end
function OnRunning(speed: number)
if enemyHumanoid.Health < 1 then return end
if chaseTrack.IsPlaying then return end
enemy.AttributeChanged:Connect(function(attribute)
if attribute ~= "Chasing" then return end
if attribute == true then
wanderTrack:Stop()
chaseTrack:Play()
else
chaseTrack:Stop()
wanderTrack:Play()
end
end)
idleTrack:Stop()
end
-- Runtime;
idleTrack:Play()
enemyHumanoid.Died:Connect(OnEnemyDied)
enemyHumanoid.Running:Connect(OnRunning)
task.spawn(HandleIdleSounds)
server script that initiates pathfinding (global):
local sScriptService = game:GetService("ServerScriptService")
local players = game:GetService("Players")
-- Path to module;
local enemyScriptsFolder = sScriptService:WaitForChild("Enemies")
-- Module;
local pathfindingModule = require(enemyScriptsFolder.PathfindingModule)
local enemyStats = require(enemyScriptsFolder.EnemyStats)
-- Folder of existing enemies (on the map);
local enemiesFolder = workspace:WaitForChild("Enemies")
-- Functions;
function GetEnemyBehaviorType(enemy: Model): number
return enemyStats[enemy.Name]["BEHAVIOR"]
end
function GetEnemyCriticalHealthAmount(enemy: Model): number
return enemyStats[enemy.Name]["CRITICAL_HEALTH"]
end
function GetClosestPlayer(enemy: Model, limb: BasePart, closestPlayer: any): Player
local character: Model = limb.Parent
local humanoid: Humanoid = character:FindFirstChildOfClass("Humanoid")
if not character or not humanoid then return end
local targetPlayer = players:GetPlayerFromCharacter(character)
if not targetPlayer then return end
local enemyRootPart: BasePart = enemy:FindFirstChild("HumanoidRootPart")
local playerRootPart: BasePart = character:FindFirstChild("HumanoidRootPart")
-- This long if statement basically checks
-- if a player has been found or
-- is there a closer player to chase
if closestPlayer == nil or (enemyRootPart.Position - playerRootPart.Position).Magnitude < (enemyRootPart.Position - closestPlayer.Character.HumanoidRootPart.Position).Magnitude then
closestPlayer = targetPlayer
return closestPlayer
end
end
-- Runtime;
while task.wait(0.15) do
local enemies = enemiesFolder:GetChildren()
if #enemies == 0 then return end
for _, enemy in ipairs(enemies) do
local detectionPart: BasePart = enemy:FindFirstChild("DetectionPart")
local humanoid: Humanoid = enemy:FindFirstChildOfClass("Humanoid")
local rootPart: BasePart = enemy:FindFirstChild("HumanoidRootPart")
local closestPlayer = nil
local playersInBox = workspace:GetPartBoundsInBox(detectionPart.CFrame, detectionPart.Size)
-- A bit of a nested for loop,
-- but i think it's okay
for _, limb in playersInBox do
closestPlayer = GetClosestPlayer(enemy, limb, closestPlayer)
end
if closestPlayer == nil then return end
task.spawn(function() -- I despise this entire function, i hate this
if closestPlayer then
local playerCharacter: Model = closestPlayer.Character
local playerTorso: BasePart = playerCharacter:FindFirstChild("Torso")
local playerPathfindPart: BasePart = playerTorso:FindFirstChild("PathfindPart")
if not playerCharacter or not playerTorso or not playerPathfindPart then return end
local targetPosition = playerPathfindPart.Position
local enemyBehaviorType = GetEnemyBehaviorType(enemy)
-- God this fucking code right here is so bad
-- and nested, someone help me
if enemyBehaviorType == 0 then
local enemyCriticalHealth = GetEnemyCriticalHealthAmount(enemy)
if humanoid.Health <= enemyCriticalHealth then
pathfindingModule.Flee(enemy)
else
pathfindingModule.Chase(humanoid, targetPosition)
enemy:SetAttribute("Chasing", true)
end
else
pathfindingModule.Chase(humanoid, targetPosition)
enemy:SetAttribute("Chasing", true)
end
else
-- Long ass if statement that checks
-- if the enemy can wander
if enemy:GetAttribute("WanderCooldown") == false and enemy:GetAttribute("Wandering") == false and enemy:GetAttribute("Chasing") == false then
pathfindingModule.Wander(humanoid)
else
if enemy:GetAttribute("Wandering") == false then
humanoid:MoveTo(rootPart.Position)
end
end
end
end)
end
end
i am literally cuddling the enemies and they’re not doing anything
the humanoid rootpart is unanchored, i’m really confused