Which NPC saw me

Ok so i’ve seen this post and i used the script for my game, in the final part where is the last function you can put anything you want the script to do, but i can’t script the last thing because its pretty difficult.
I want the script to check which NPC saw me and then move the player camera to the NPC’s face, its difficult because the script works with tags and its not for any individual humanoid.
If this is not possible then i have to find another way to do this. Can someone tell me what should i put in the script?

The easiest way to do this is probably to have the checkingsight function to return the last object as opposed to true:

local function checkSight(npc)
	local objectfound = nil
	local detectable = {}

	local characters = getCharacters()
	local taggedObjects = CollectionService:GetTagged("Detectable")

	for index, character in characters do
		table.insert(detectable, character)
	end

	for index, object in taggedObjects do
		table.insert(detectable, object)
	end

	for index, object in detectable do
		if object:IsA("Model") then
			object = object.PrimaryPart
		end

		local headPosition = npc.Head.Position

		local objectPosition = object.Position
		local headCFrame = npc.Head.CFrame

		local direction = (objectPosition - headPosition).Unit
		local lookVector = headCFrame.LookVector

		local dotProduct = direction:Dot(lookVector)
		local angle = math.deg(math.acos(dotProduct))

		local distance = (headPosition - objectPosition).Magnitude

		if angle > fieldOfView then
			continue
		end

		if distance > viewRange then
			continue
		end

		if raycast(npc, headPosition, objectPosition) then
			return
		end

		if object:IsA("Model") then
			objectfound = object.Parent
		else
			objectfound = object
		end

		return objectfound
	end
end

Then, alter your code to find the player from the object returned and fire a remoteevent (which you can make and put in replicatedstorage for example. It doesn’t really matter where it is, just make sure it’s properly referenced).

for index, npc in npcModels do
	local humanoid = npc:FindFirstChildOfClass("Humanoid")

	if not npc:IsA("Model") then
		continue
	end

	if not humanoid then
		continue
	end

	local function checking()
		while task.wait(1) do
			local objectfound = checkSight(npc)
			if checkSight(npc) then
				if PlayerService:GetPlayerFromCharacter(objectfound) then
					local RemoteEvent = game.ReplicatedStorage.RemoteEvent -- ensure this is properly referencing your remoteevent
					local player = PlayerService:GetPlayerFromCharacter(objectfound)
					RemoteEvent:FireClient(player, npc)
				end
			else
				-- Code for when an NPC does not see a detectable object
			end
		end
	end

	coroutine.wrap(checking)()
end

Then add a localscript to starter character scripts with something along the lines of this:

local RemoteEvent = game.ReplicatedStorage.RemoteEvent

RemoteEvent.OnClientEvent:Connect(function(npc)
	-- This function moves the player's camera to the npc
	local npchead = npc.Head
	if not npchead then return end
	game.Workspace.CurrentCamera.CameraType = Enum.CameraType.Scriptable
	game.Workspace.CurrentCamera.CFrame = CFrame.new(Vector3.new(npchead.CFrame.Position + 5*npchead.CFrame.LookVector.Unit), Vector3.new(npchead.CFrame.Position))
	task.wait(5)
	game.Workspace.CurrentCamera.CameraType = Enum.CameraType.Custom
end)

The function given in the localscript is just a placeholder, an idea of how looking at the npc’s face would vaguely work. In reality, you will want to customise this to better fit your needs. I haven’t tested any of the code provided, so let me know if you run into issues, but do take the time to properly look over all of the edits to understand why the edits were made and how everything works.

It doesn’t work but there isn’t any error, also many times i struggle with remoteevents

Whenever you run into issues like this, you can use print functions to figure out where your code isn’t working.

Add a print(1) after the RemoteEvent firing in the serverscript and a print(2) function at the start of the function in the localscript (just before local npchead = npc.Head). Run it and let me know what prints in the console. If 1 and 2 print, then everything is running except potentially the actual camera movement function. If some of those don’t print then there’s something wrong earlier on.

No print works and i even put print(0) after the line if PlayerService:GetPlayerFromCharacter(objectfound) then
And it doesn’t work

can you print(objectfound) before the if PlayerService:GetPlayer…

Yeah it returns HumanoidRootPart so i believe that after the if PlayerService:GetPlayer the code doesn’t work

yup as I suspected. replace

PlayerService:GetPlayerFromCharacter(objectfound)

with

PlayerService:GetPlayerFromCharacter(objectfound.Parent)

I assumed that given all of the “if object is a model” stuff in the original code linked in your original post it would return the model itself, but it seems it was still just returning the primary part.

Gives me the Remoteevent error: “FireClient: player argument must be a Player object”

replace the other playerservice line in the same way as my previous comment. So player = Playerservice…(objectfound.Parent) as opposed to objectfound

Okay its starting to become something but now i think the issue is the camera, it stops but it doesn’t move to the NPC’s face

I forgot to say that my NPCs are constantly moving because i scripted them and idk if the issue is because of their movement, also it prints 2

The issue was because of the way I defined the new camera CFrame (I used Vector3.new even though they were already vectors). I went ahead and also fixed the movement thing by adding a RenderStepped connection:

local RemoteEvent = game.ReplicatedStorage.RemoteEvent
local RunService = game:GetService("RunService")

RemoteEvent.OnClientEvent:Connect(function(npc)
	-- This function moves the player's camera to the npc
	local npchead = npc.Head
	if not npchead then return end
	game.Workspace.CurrentCamera.CameraType = Enum.CameraType.Scriptable

	local connection
	connection = RunService.RenderStepped:Connect(function()
		game.Workspace.CurrentCamera.CFrame = CFrame.new(npchead.CFrame.Position + 5*npchead.CFrame.LookVector.Unit, npchead.CFrame.Position)
	end)

	task.wait(5)
	connection:Disconnect()
	game.Workspace.CurrentCamera.CameraType = Enum.CameraType.Custom
end)

It really works now, THANK YOU!, this was one of my major problem in my game

No worries. Do try to learn more about RemoteEvents as they’re incredibly useful in basically any situation for which you want the Server and Client to communicate (many developers use other means of replicating data with modules, but remoteevents are one of the easiest in-built features).

If you have no other issues do mark the post as solved.

Yeah im really struggling with them but im trying to understand, thanks.

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