Check If Part is Visible Buggy

Hi everyone,

I am making SCP-173 (peanut) for an SCP themed game. If you don’t know, SCP 173 will kill the player when they are not looking at it. I have attempted to replicate this in ROBLOX using raycasting and :WorldToViewportPoint(). This system rarely works and I am unsure why. I have attached some videos below for you to check out.

Third Person:
https://gyazo.com/3cdc0a1b1ce68e8cad2cadca99a1445e

First Person:
https://gyazo.com/08702a25c4a32bfda686d0a566804274

The output on both of these prints “Not Visible” even though you can see it is. I will attach the code below.

Local Script:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Events = ReplicatedStorage:WaitForChild("Events")
local RemoteEvent = Events.SCP173Magnitude
local Player = game:GetService("Players").LocalPlayer
local SCPs = game.Workspace.SCPs
local SCP173 = SCPs.SCP173
local SCP173Model = SCP173.PeanutModel
local SCP173PrimaryPart = SCP173.PeanutModel.PrimaryPart
local MaxRange = 20

local function IsVisible()
	local partToCheck = workspace.SCPs.SCP173.PeanutModel.PrimaryPart
	--local partToCheck = workspace.SCPs.SCP173.PeanutModel.Checker
	local camera = workspace.CurrentCamera

	local vector, inViewport = camera:WorldToViewportPoint(partToCheck.Position)
	local onScreen = inViewport and vector.Z > 0

	local ray = camera:ViewportPointToRay(vector.X, vector.Y, 0)
	local raycastParams = RaycastParams.new()
	raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
	raycastParams.FilterDescendantsInstances = {partToCheck, Player.Character}
	local raycastResult = workspace:Raycast(ray.Origin, ray.Direction * 1000, raycastParams)

	local isVisible = onScreen and not raycastResult

	return isVisible
end

while wait(1) do
	if Player:DistanceFromCharacter(SCP173PrimaryPart.Position) <= MaxRange then
	
		local isVisible = IsVisible()
		if isVisible then
			print("visible")
			--local name = game.Players.LocalPlayer.Name
		else
			print("not visible")
			local char = Player.Character
			game.ReplicatedStorage.Events.SCP173Kill:FireServer(char)
		end
	else
		
	end
end

Server Script:

local SCPs = game.Workspace.SCPs
local SCP173 = SCPs.SCP173
local SCP173Model = SCP173.PeanutModel
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Events = ReplicatedStorage:WaitForChild("Events")
local RemoteEvent = Events.SCP173Kill
local MagEvent = Events.SCP173Magnitude

RemoteEvent.OnServerEvent:Connect(function(p, char)
	print("Event Received")
	local humanoid = char:FindFirstChild("Humanoid")
	SCP173Model:MoveTo(char.HumanoidRootPart.Position)
	humanoid.Health = 0
end)

2 Likes

Instead of using a ray, I’d use .magnitude instead

	local Root = Character:WaitForChild("HumanoidRootPart")
        local Dis = 250 -- Distance to detect if they are looking
	for i, v in ipairs(game.Workspace:GetChildren()) do -- Loops through workspace to find players
	
		local Target = v:FindFirstChild("HumanoidRootPart") -- The targets Humanoidrootpart
		if Target and v ~= Character and v:FindFirstChild("HumanoidRootPart") then -- Checks if target is a player and that character isn't the subject

			if (Root.Position - Target.Position).Magnitude < Dis  then -- If target is close enough to subject
               if  Target.CFrame:toObjectSpace(Character.PrimaryPart.CFrame).Z <  0  then -- If target is looking at subject
-- code of what you want to do
            end
		end	
	end
end
2 Likes

I believe it should be whitelist and then the player’s character should be removed so that only the model’s primary part is allowed.

raycastParams.FilterType = Enum.RaycastFilterType.Whitelist
raycastParams.FilterDescendantsInstances = { partToCheck }

Nonetheless, I have a feeling that this will not work because it will not identify a wall as it just permits the model’s primary component. Remove the raycastParams and replace them with an if statement if the ray instance is the model’s primary part.

return onScreen and raycastResult == partToCheck
1 Like

Where would I put this script? I can’t find a variable that declares what the actual SCP is. Would I put this script inside the 173 model?

You could just put this in a script inside of scp.

local Subject = script.Parent -- Defines it, or you can change the variable name to character

How would this work though? What is character referencing in the script below? If I placed this inside the SCP model it would not work even with subject defined to the primary part.

local Root = Character:WaitForChild("HumanoidRootPart")
local Dis = 250 -- Distance to detect if they are looking
for i, v in ipairs(game.Workspace:GetChildren()) do -- Loops through workspace to find players

	local Target = v:FindFirstChild("HumanoidRootPart") -- The targets Humanoidrootpart
	if Target and v ~= Character and v:FindFirstChild("HumanoidRootPart") then -- Checks if target is a player and that character isn't the subject

		if (Root.Position - Target.Position).Magnitude < Dis  then -- If target is close enough to subject
			if  Target.CFrame:toObjectSpace(Character.PrimaryPart.CFrame).Z <  0  then -- If target is looking at subject
				-- code of what you want to do
			end
		end	
	end
end

You can’t copy and paste the script. That’s not what I was showing I was just giving an example on the key componets on how to make the script work. For example, you’ll need to use magnitude to get the players around the subject.

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