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.
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)
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
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.
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.