My in-game enemies lose intelligence when being spawned?

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

Could you check if animation and pathfinding functions are being fired at all? If they are being fired, are there any errors?

If they are being fired with no errors, I assume something might be wrong with the Humanoid’s?

okay, a bit of a mistake on my end, i should’ve done continue instead of return in the while loop in the global script,

with a bit of rewriting… i will fix this

image

i guess it’s been solved, technically?
i mean, just incase i get another problem related to this i’ll let you know

for now i’m going silent

Alright, good luck! Cool game by the way, seems to be inspired by Decaying Winter, love that game.

well, i fixed the initiating issue

my pathfinding is uhm, extremely broken right now, but i’ll fix that tomorrow!

as for my animations, they are still a bit hesitant to play

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("Wander")

-- 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)

not sure what’s happening

someone finally noticed me… i’m going to cry…
i’ve been working on a “fan-game” since 2022, i’ve ascended so much since then

i’m actually aiming for an early 2025 release!!!

Could you check if the animations are playing with AnimationTrack.IsPlaying? Maybe they are playing but the animation was just uploaded wrong. I would also just check if each if-statement is being fired properly.

If all of those are working as intended, then maybe you might be working in a group? If someone else is uploading the animations, and it isn’t uploaded to the group (if you’re working in one), then you can’t see it in studio (for some reason), but you can see when you’re in the actual game. Try testing the game on Roblox outside of Studio, and see if it shows.

this is an instant no, this has been a solo project since the start, aside from third party models, which are still imported by me

intelligence was gained back, buuut pathfinding is broken,i guess i’ll make a different topic

1 Like

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