Hi there, I’m making a script that if a player comes close in a 30 studs radius. The head will look at the player, if the head gets at a certain angle, the body will rotate/move itself with the head. So it stays naturally and the head doesn’t spin 360 degrees. However, I can’t seem to get why this isn’t working. It just doesn’t work, and nothing shows up in the output window.
The script is located in the NPC, it has a humanoid and humanoidrootpart, it’s an R15 NPC and the script is a server sided script.
Thank you.
local PlayerService = game:GetService("Players")
local npc = script.Parent
local Range = 30
local angleThreshold = 30
local hasSeenPlayer = false
local function getAngleBetweenVectors(vec1, vec2)
return math.deg(math.acos(vec1:Dot(vec2) / (vec1.magnitude * vec2.magnitude)))
end
local function CheckLineOfSight(Start, End)
local RaycastParams = RaycastParams.new()
RaycastParams.FilterType = Enum.RaycastFilterType.Exclude
RaycastParams.FilterDescendantsInstances = {npc, unpack(PlayerService:GetPlayers())}
local RaycastResult = workspace:Raycast(Start, End - Start, RaycastParams)
return RaycastResult == nil
end
local function updateVisibilityFlag()
local canSeePlayer = false
for _, b in pairs(PlayerService:GetPlayers()) do
local Character = b.Character
if Character then
local NPCToCharacter = (Character.Head.Position - npc:WaitForChild("Head").Position).Unit
local NPCLookVector = npc:WaitForChild("Head").CFrame.LookVector
local DotProduct = NPCToCharacter:Dot(NPCLookVector)
local Angle = math.deg(math.acos(DotProduct))
local Distance = (npc.HumanoidRootPart.Position - Character.HumanoidRootPart.Position).Magnitude
if Angle <= angleThreshold and Distance <= Range and CheckLineOfSight(npc.Head.Position, Character.Head.Position) then
canSeePlayer = true
end
end
end
hasSeenPlayer = canSeePlayer
end
local function rotateHeadTowardsPlayer(player)
if player and hasSeenPlayer then
local playerCharacter = player.Character
if playerCharacter then
local playerHead = playerCharacter:FindFirstChild("Head")
if playerHead then
local direction = (playerHead.Position - npc.Head.Position).unit
local currentLookVector = npc.Head.CFrame.LookVector
local angle = getAngleBetweenVectors(currentLookVector, direction)
if angle > angleThreshold then
local lookAtCFrame = CFrame.lookAt(npc.Head.Position, playerHead.Position, Vector3.new(0, 1, 0))
npc.Head.CFrame = lookAtCFrame
end
end
end
end
end
local function checkPlayerVisibility()
while true do
wait(1)
updateVisibilityFlag()
end
end
local function checkPlayerProximity()
while true do
wait(0.5)
local players = game.Players:GetPlayers()
for _, player in pairs(players) do
local distance = (npc.Head.Position - player.Character.HumanoidRootPart.Position).magnitude
if distance < 30 then
rotateHeadTowardsPlayer(player)
end
end
end
end
spawn(checkPlayerVisibility)
spawn(checkPlayerProximity)