I’m trying to make a monster in Roblox that will attack you if you look at it’s face. Ideally, this would be to look at it with your player, not your screen.
I wrote a script that detects if your player is facing at the part, and it works great, but it doesn’t take account of walls.
I’ve tried RayCasting, but it was really buggy and only worked if I looked directly at the center of the part. I set the sensitivity to higher, but it really just didn’t work.
This is my facing part code. I would like to somehow make it so it doesn’t work through walls, but I don’t know how.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RemoteEvent = ReplicatedStorage:WaitForChild("Viewed")
local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local npc = workspace:WaitForChild("lookpart")
local function CanSee(playerHead, npcHead, maxAngle)
local lookDirection = playerHead.CFrame.LookVector
local towardsNpc = (npcHead.Position - playerHead.Position).Unit
local dotProduct = lookDirection:Dot(towardsNpc)
local cosineAngle = math.cos(maxAngle)
return dotProduct >= cosineAngle
end
-- EXAMPLE
game:GetService("RunService").Stepped:Connect(function()
if CanSee(character.Head, npc, 20) then
npc.BrickColor = BrickColor.Green()
RemoteEvent:FireServer(character.Name)
else
npc.BrickColor = BrickColor.Red()
end
end)
So, it looks like you’ve got math to tell if you are facing the monster, with a given max angle. I think to complete your goal you do need to raycast, but it doesn’t necessarily have to be using the direction that you’re character’s head is facing.
I’d treat it as 2 passes.
Check if it’s in the view cone (you’ve got this)
Check if there is anything obstructing the line of sight between your head and the monster.
For checking line of sight, you can cast a ray from your head to the monster head. (Don’t use the look direction of your head)
That’s a great idea, and it works, however, I still get the issue where I have to be looking directly at the head for it to work.
Is there something I should do to my raycast code?
local SCP096 = game.Workspace:WaitForChild("SCP-096") --// Make sure that the script waits until 096 is out of the ServerStorage
local SCP096Head = SCP096:WaitForChild("Head")
--// ^^^^^^ SCP-096 is the monster by the way.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RemoteEvent = ReplicatedStorage:WaitForChild("Viewed") --// Find RemoteEvent that triggers when looked
local Player = game.Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local PlayerHead = Character:WaitForChild("Head")
while true do
local Direction = SCP096Head.Position - PlayerHead.Position
local Parameters = RaycastParams.new()
Parameters.FilterType = Enum.RaycastFilterType.Blacklist --// Make sure these parts don't get in the way. Will make a collision group later
Parameters.FilterDescendantsInstances = {SCP096:WaitForChild("Jaw"), SCP096Head:WaitForChild("Eyes"), SCP096:WaitForChild("UpperTorso"), SCP096:WaitForChild("LowerTorso"), Character:WaitForChild("Head")}
local RaycastResult = workspace:Raycast(PlayerHead.Position, Direction, Parameters)
if RaycastResult and RaycastResult.Instance then
if RaycastResult.Instance == SCP096Head then
print("looked")
end
end
task.wait(0.1) --// Make sure the loop doesnt crash the game
end