so i have a script here that checks to see if a placeholder part is within the field of view of an object. it works reasonably well, but when i try to use CollectionService to check if the primary parts of tagged models are in the field of view, it does not function. i have no idea why.
(for context, this is a LocalScript inside of a tool)
i have tried to remedy this problem with a couple of solutions, none of which worked:
-
looping through every instance with the tag, checked to see if the instance was a model, and called the “check_fov()” function, using the primary part as the second argument.
-
using a table to loop through every tagged instance, checking to see if they were a valid instance, and then checking the field of view.
here is the script that works with the placeholder object:
-- services
local run_service = game:GetService("RunService")
local collection_service = game:GetService("CollectionService")
-- other variables
local phone_equipped = false
local enemy_tag = "invisible_enemy"
local visibility_tag = "is_visible"
local rbx_connection
local npc_fov = 70
local transparency_threshold = 0.5
function has_obstacle(start_position, end_position, filter_instances, fov_angle)
local ray_params = RaycastParams.new()
ray_params.FilterType = Enum.RaycastFilterType.Exclude
ray_params.FilterDescendantsInstances = filter_instances
local hit_result = workspace:Raycast(start_position, end_position - start_position, ray_params)
if hit_result and hit_result.Instance and hit_result.Instance.Transparency >= transparency_threshold then
return false
end
return hit_result ~= nil
end
function check_fov(sight_part, target_obj, npc_fov)
if not phone_equipped then
return
end
local field_of_view_angle = math.rad(npc_fov)
local npc_to_character = (target_obj.Position - sight_part.Position).Unit
local npc_look_vector = sight_part.CFrame.LookVector
local dot_product = npc_to_character:Dot(npc_look_vector)
if dot_product > math.cos(field_of_view_angle / 2) and not has_obstacle(sight_part.Position, target_obj.Position, {sight_part, target_obj}, field_of_view_angle) then
sight_part.Color = Color3.fromRGB(255, 76, 76)
sight_part:SetAttribute("status", "i can see an enemy!")
collection_service:AddTag(target_obj, visibility_tag)
else
sight_part.Color = Color3.fromRGB(66, 255, 151)
sight_part:SetAttribute("status", "i cannot see any enemies")
collection_service:RemoveTag(target_obj, visibility_tag)
end
end
local tool = script.Parent
local handle = tool:WaitForChild("Handle")
local player_cube = workspace:WaitForChild("main_cube")
tool.Equipped:Connect(function()
phone_equipped = true
rbx_connection = run_service.PreSimulation:Connect(function()
check_fov(handle, player_cube, npc_fov)
end)
end)
tool.Unequipped:Connect(function()
if rbx_connection then
rbx_connection:Disconnect()
end
phone_equipped = false
-- forcibly change statuses
handle:SetAttribute("status", "i cannot see any enemies")
collection_service:RemoveTag(player_cube, visibility_tag)
end)