Issue with monster

I am creating a monster in Roblox that is supposed to chase the player and make a sound (a scream) when it detects the player. However, there is a bug: when the player leaves the detection radius and then re-enters it, the monster starts screaming again, and this can be repeated infinitely by “going in and out” of the detection radius.

What happens:

  1. When the player enters the detection radius of the monster, it starts chasing the player and the monster makes a scream.
  2. If the player leaves the detection radius, the chase stops, and the scream stops.
  3. However, when the player re-enters the detection radius, the monster screams again and starts chasing.
  4. If this is done multiple times, the monster can be “bugged,” making it scream every time the player enters the detection radius.

Here is a video:

Here are scripts:

Main

local ws = game:GetService("Workspace")
local rs = game:GetService("RunService")
local pfs = game:GetService("PathfindingService")
local SoundService = game:GetService("SoundService")

local npc = script.Parent
local hum = npc:WaitForChild("Monster")
local root = npc.HumanoidRootPart
local chasing = npc:WaitForChild("Chasing") 
local targetVal = npc:WaitForChild("Target")

local attack = false
local canAttack = npc.Configuration.CanAttack
local canFollowNPCs = false
local anims = {
	aLeft = hum:LoadAnimation(script.AttackLeft),
	aRight = hum:LoadAnimation(script.AttackRight),
	aHeavy = hum:LoadAnimation(script.AttackHeavy)
}
local damage = npc.Configuration.Damage
local attackDelay = npc.Configuration.AttackDelay
local rSpeed = npc.Configuration.RunSpeed
local wSpeed = npc.Configuration.WalkSpeed

local hitSounds = {
	SoundService:WaitForChild("Hit1"),
	SoundService:WaitForChild("Hit2"),
	SoundService:WaitForChild("Hit3")
}
local swingSound = SoundService:WaitForChild("Swing")


local currentTarget = nil
local lastChasingState = false
local lostTargetTime = 0
local MAX_TARGET_LOST_TIME = 2 


function getNearestTarget()
	local dist = 44.5
	local char

	if canFollowNPCs then
		for _, v in pairs(ws:GetChildren()) do
			if v:FindFirstChild("Humanoid") and v:FindFirstChild("HumanoidRootPart") and v ~= npc then
				local vHum = v:WaitForChild("Humanoid")
				local vRoot = v:WaitForChild("HumanoidRootPart")
				if vHum.Health > 0 then
					local distance = (vRoot.Position - root.Position).Magnitude
					if distance <= dist then
						dist = distance
						char = v
					end
				end
			end
		end
	else
		for _, v in pairs(game.Players:GetPlayers()) do
			if v.Character then
				local vChar = v.Character
				if vChar:FindFirstChild("Humanoid") and vChar:FindFirstChild("HumanoidRootPart") and vChar ~= npc then
					local vHum = vChar:WaitForChild("Humanoid")
					local vRoot = vChar:WaitForChild("HumanoidRootPart")
					if vHum.Health > 0 then
						local distance = (vRoot.Position - root.Position).Magnitude
						if distance <= dist then
							dist = distance
							char = vChar
						end
					end
				end
			end
		end
	end
	return char
end


function isTargetVisible(target)
	if not target then return false end
	local targetRoot = target:FindFirstChild("HumanoidRootPart")
	if not targetRoot then return false end

	local origin = root.Position
	local direction = (targetRoot.Position - origin).Unit * 500
	local ray = Ray.new(origin, direction)
	local hit, _ = workspace:FindPartOnRayWithIgnoreList(ray, {npc})

	return hit and hit:IsDescendantOf(target)
end

rs.Heartbeat:Connect(function()
	if root.Anchored == false then
		root:SetNetworkOwner(nil)
	end

	local target = getNearestTarget()
	local now = os.clock()


	if target then
		currentTarget = target
		lostTargetTime = 0
	elseif currentTarget and (now - lostTargetTime) < MAX_TARGET_LOST_TIME then
		
		target = currentTarget
	else
		currentTarget = nil
	end

	if target then
		local targetRoot = target:FindFirstChild("HumanoidRootPart")
		local targetHum = target:FindFirstChild("Humanoid")
		if not targetRoot or not targetHum or targetHum.Health <= 0 then
			currentTarget = nil
			if chasing.Value then
				chasing.Value = false
			end
			return
		end

		local distance = (root.Position - targetRoot.Position).Magnitude

		
		if distance < 44.5 then
			if not chasing.Value then
				chasing.Value = true
			end

			
			local isVisible = isTargetVisible(target)
			if isVisible or distance < 20 then 
				local createPath = pfs:CreatePath({
					AgentHeight = hum.HipHeight,
					AgentRadius = 1.6,
					AgentCanJump = true,
					WaypointSpacing = math.huge
				})
				createPath:ComputeAsync(root.Position, targetRoot.Position)
				for i, v in pairs(createPath:GetWaypoints()) do
					if i ~= 1 then
						if v.Action == Enum.PathWaypointAction.Jump then
							hum.Jump = true
						end
						hum:MoveTo(v.Position)
						hum.MoveToFinished:Wait()
					end
				end
			end
		elseif distance > 46.0 and chasing.Value then
			lostTargetTime = now
			chasing.Value = false
		end
	elseif chasing.Value then
		chasing.Value = false
	end
end)


task.spawn(function()
	while true do
		task.wait()

		local target = currentTarget

		if root.Anchored == false then
			root:SetNetworkOwner(nil)
		end

		if target then
			local targetRoot = target:FindFirstChild("HumanoidRootPart")
			local targetHum = target:FindFirstChild("Humanoid")
			if not targetRoot or not targetHum then continue end

			local distance = (root.Position - targetRoot.Position).Magnitude

			if distance < 5.8 then
				if attack == false and canAttack.Value == true then
					attack = true

					if swingSound then
						swingSound:Play()
					end

					local random = math.random(1, 2)

					if targetHum.Health > damage.Value then
						if random == 1 then
							anims.aRight:Play()
						else
							anims.aLeft:Play()
						end
					elseif targetHum.Health <= damage.Value then
						anims.aHeavy:Play()
					end

					task.wait(0.25)

					if distance < 5.4 then
						local hitSound = hitSounds[math.random(1, #hitSounds)]
						if hitSound then
							hitSound:Play()
						end
						targetHum:TakeDamage(damage.Value)
					end

					task.spawn(function()
						task.wait(attackDelay.Value)
						attack = false
					end)
				end
			end
		end
	end
end)

SpeedMain

local npc = script.Parent
local hum = npc:WaitForChild("Monster")
if not hum:IsA("Humanoid") then
	hum:Destroy()
	error("Monster is not a Humanoid!")
end

local animator = hum:FindFirstChildOfClass("Animator")
local screamAnim = script:WaitForChild("Scream")
local scream = animator and screamAnim and animator:LoadAnimation(screamAnim)
local chasing = npc:WaitForChild("Chasing")
local rSpeed = npc.Configuration.RunSpeed
local wSpeed = npc.Configuration.WalkSpeed
local root = npc.HumanoidRootPart
local screamSound = npc:WaitForChild("Head"):WaitForChild("Rake_Scream")

local isScreaming = npc:FindFirstChild("IsScreaming") or Instance.new("BoolValue")
isScreaming.Name = "IsScreaming"
isScreaming.Value = false
isScreaming.Parent = npc


local function updateSpeed()
	if isScreaming.Value then
		hum.WalkSpeed = 0
	elseif chasing.Value then
		hum.WalkSpeed = rSpeed.Value
	else
		hum.WalkSpeed = wSpeed.Value
	end
end


local function handleChasing()
	if chasing.Value and not isScreaming.Value then
		isScreaming.Value = true

		
		if screamSound then screamSound:Play() end
		if scream then 
			scream:Play() 
			scream.Stopped:Wait()
		end

		isScreaming.Value = false
	end
	updateSpeed()
end


chasing.Changed:Connect(handleChasing)
isScreaming.Changed:Connect(updateSpeed)


updateSpeed()

so what exactly did you want it to do instead? Scream once when it initially detects the player and doesn’t scream again or did you want the monster to chase the player ignoring the detection radius when player triggers it preventing the player to go “in and out”

pls be specific with your goal

Did you see the video sir? /////////////////////

The monster should not be “retriggered” just because the player moves slightly out and back into range

Nevermind, I fixed it right now

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