Stop NPCs movement when part goes behind it

I have this simple script that has this goalie change its direction to face a hockey puck. I’m trying to have it so when the hockey puck goes behind the goal and past the NPCs “fov” that it will ignore it and stops moving toward it until the hockey comes back out from either side of the goal.

Here is the simple server script that moves the NPC:

local RunService = game:GetService("RunService")

local goalie = script.Parent.Goaltender
local puck = script.Parent.puckValue.Value

local speed = 14

RunService.Heartbeat:Connect(function()
	local goaliePosition = goalie.PrimaryPart.Position
	local direction = puck.Position - goaliePosition

	direction = Vector3.new(direction.X, 0, direction.Z).Unit
	goalie.Humanoid:MoveTo(goaliePosition + direction * speed)
end)

You could check the position of the goalie each frame, and clamp the goaliePosition moveto so it doesn’t go behind the net. For more realism you could program something specific so the goalie doesn’t move the other side until the puck has crossed atleast the halfway mark behind the net.

In order to do an NPCs FoV system you can easily implement yours using Vector3:Dot(), Dot returns how much two vectors are going in the same direction.

Here’s an implementation:

local head = -- (your npc's head)
local hockey = -- (the hockey)

local headtohockey = (hockey.Position - head.Position).Unit -- get the direction in which the hockey is at relative to the NPC's head
local lookVector = head.CFrame.LookVector -- get where the npc is looking at

local similarity = headtohockey:Dot(lookVector) -- compare how different the two directions are

Note that Dot returns a number from -1 to 1. I’d recommend you checking if similarity is bigger or equal than 0.5 because that means that the NPC has a 45° angle FoV to see the hockey. You can implement it this way:

local RunService = game:GetService("RunService")

local goalie = script.Parent.Goaltender
local puck = script.Parent.puckValue.Value

local speed = 14
local FoV = 0.5

RunService.Heartbeat:Connect(function()
	local goalieLook = goalie.Head.CFrame.LookVector
	local unitDirection = (puck.Position - goalie.Head.Position).Unit
	local comparaison = unitDirection:Dot(goalieLook)

	if comparaison < 0.5 then return end -- the npc is not looking at the puck, avoid this routine from executing more code

	local goaliePosition = goalie.PrimaryPart.Position
	local direction = puck.Position - goaliePosition

	direction = Vector3.new(direction.X, 0, direction.Z).Unit
	goalie.Humanoid:MoveTo(goaliePosition + direction * speed)
end)

And also, if you want the NPC to avoid going to certain places you can check if the puck is colliding with certain parts using workspace:GetPartsInPart(). However, If I were you, I would just hardcode the NPC to check the puck’s position and if the X or Z value is higher than a number then stop its movement, hehe…

1 Like

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