Hello, I’ve been working on a Script that lets me check if a parts on the screen and I’m having a issue well I can’t figure a way to check what face it is because I want to be able to check if the front face is on the screen not just the main part.
– Thank you.
repeat
task.wait(2.5)
until game.Loaded
local Player = game:GetService("Players").LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local RunServiceKey = "OnScreenKey"
local RunService = game:GetService("RunService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Remotes = ReplicatedStorage:WaitForChild("Remotes")
local LookedEvent = Remotes:WaitForChild("Looked")
local Camera = workspace.CurrentCamera
local Part = workspace:WaitForChild("Roblox").Head
local HasLooked = false
local function FireServer()
local Humanoid = Character:FindFirstChild("Humanoid")
if not Humanoid then return end
if Humanoid.Health <= 0 then return end
if HasLooked == true then return end
HasLooked = true
warn("Uh oh.")
LookedEvent:FireServer()
end
local function Main()
local ScreenVector, OnScreen = Camera:WorldToViewportPoint(Part.Position)
if OnScreen then
FireServer()
workspace.Baseplate.Color = Color3.new(0, 1, 0)
else
local CornerOnScreen = false
for X = -1, 1, 2 do
for Y = -1, 1, 2 do
for Z = -1, 1, 2 do
local Position = Part.CFrame:ToWorldSpace(CFrame.new(X * Part.Size.X / 2, Y * Part.Size.Y / 2, Z * Part.Size.Z / 2)).Position
local ScreenVector, OnScreen = Camera:WorldToViewportPoint(Position)
if OnScreen then
CornerOnScreen = true
break
end
end
if CornerOnScreen then
break
end
end
if CornerOnScreen then
break
end
end
if CornerOnScreen then
FireServer()
workspace.Baseplate.Color = Color3.new(0, 1, 0)
else
workspace.Baseplate.Color = Color3.new(1, 0, 0)
end
end
end
RunService:BindToRenderStep(RunServiceKey, 1, Main)
Player.CharacterAdded:Connect(function(NewCharacter)
Character = NewCharacter
repeat task.wait(5) until NewCharacter:FindFirstChild("Humanoid")
HasLooked = false
print("Reset HasLooked")
end)
I think I missed something, the “OnScreen” part doesn’t actually check whether the part is occluded or not. Just if the camera is facing it. So, one thing you can try is to fire a raycast towards that point and see if it results in the part, but in order to make it accurate, you will have to exclude transparent parts.
--if OnScreen is true, fire a raycast as well
local RaycastResult = workspace:Raycast(Camera.CFrame.Position, CFrame.lookAt(Camera.Position, Part.Position + Part.CFrame.LookVector * Part.Size.Z / 2, Params)
if RaycastResult and RaycastResult.Instance == Part then
--It is on the screen and is visible in the viewport.
I think I missed another thing. We have to check the normal of the raycast after it’s been done.
--if OnScreen is true, fire a raycast as well
local RaycastResult = workspace:Raycast(Camera.CFrame.Position, CFrame.lookAt(Camera.Position, Part.Position, Params)
if RaycastResult and RaycastResult.Instance == Part and Part.CFrame.LookVector:FuzzyEq(RaycastResult.Normal) then
--It is on the screen and is visible in the viewport.
Now, this will fail if the part you’re checking isn’t a rectangular prism or has a flat front surface. For a MeshPart, the collision should be set to Box.
That seems to have been a typo. Yes, Camera.CFrame.Position should be correct, but it seems like after I deleted some of the previous code it messed up the syntax. Sorry about that.
--if OnScreen is true, fire a raycast as well
local RaycastResult = workspace:Raycast(Camera.CFrame.Position, CFrame.lookAt(Camera.CFrame.Position, Part.Position).LookVector * 1000, Params)
if RaycastResult and RaycastResult.Instance == Part and Part.CFrame.LookVector:FuzzyEq(RaycastResult.Normal) then
--It is on the screen and is visible in the viewport.
Currently, this should work perfectly fine however if there’s any occluding parts like accessories or “Hair” in the character, this will not run, even if the part is clearly visible. So, you may need to adjust that later by adding more instances into the filter.
repeat
task.wait(2.5)
until game.Loaded
print("LOADED")
local Player = game:GetService("Players").LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local RunServiceKey = "OnScreenKey"
local RunService = game:GetService("RunService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Remotes = ReplicatedStorage:WaitForChild("Remotes")
local LookedEvent = Remotes:WaitForChild("Looked")
local Camera = workspace.CurrentCamera
local Part = workspace:WaitForChild("Roblox").Head
local HasLooked = false
local Params = RaycastParams.new()
Params.FilterDescendantsInstances = {Player.Character}
Params.FilterType = Enum.RaycastFilterType.Exclude
local function FireServer()
local Humanoid = Character:FindFirstChild("Humanoid")
if not Humanoid then return end
if Humanoid.Health <= 0 then return end
if HasLooked == true then return end
HasLooked = true
warn("Uh oh.")
LookedEvent:FireServer()
end
local function Main()
local ScreenVector, OnScreen = Camera:WorldToViewportPoint(Part.Position)
if OnScreen then
local RaycastResult = workspace:Raycast(Camera.CFrame.Position, CFrame.lookAt(Camera.CFrame.Position, Part.Position).LookVector * 1000, Params)
if RaycastResult and RaycastResult.Instance == Part and Part.CFrame.LookVector:FuzzyEq(RaycastResult.Normal) then
FireServer()
workspace.Baseplate.Color = Color3.new(0, 1, 0)
end
else
local CornerOnScreen = false
for X = -1, 1, 2 do
for Y = -1, 1, 2 do
for Z = -1, 1, 2 do
local Position = Part.CFrame:ToWorldSpace(CFrame.new(X * Part.Size.X / 2, Y * Part.Size.Y / 2, Z * Part.Size.Z / 2)).Position
local ScreenVector, OnScreen = Camera:WorldToViewportPoint(Position)
if OnScreen then
CornerOnScreen = true
break
end
end
if CornerOnScreen then
break
end
end
if CornerOnScreen then
break
end
end
if CornerOnScreen then
local RaycastResult = workspace:Raycast(Camera.CFrame.Position, CFrame.lookAt(Camera.CFrame.Position, Part.Position).LookVector * 1000, Params)
if RaycastResult and RaycastResult.Instance == Part and Part.CFrame.LookVector:FuzzyEq(RaycastResult.Normal) then
FireServer()
workspace.Baseplate.Color = Color3.new(0, 1, 0)
end
else
workspace.Baseplate.Color = Color3.new(1, 0, 0)
end
end
end
RunService:BindToRenderStep(RunServiceKey, 1, Main)
Player.CharacterAdded:Connect(function(NewCharacter)
Character = NewCharacter
repeat task.wait(5) until NewCharacter:FindFirstChild("Humanoid")
HasLooked = false
print("Reset HasLooked")
end)
I think what you should do is put the code inside the else inside this if OnScreen then, and before you do that remove these in the if OnScreen then because there’s already one inside.
So,
if OnScreen then
local CornerOnScreen = false
for X = -1, 1, 2 do
for Y = -1, 1, 2 do
for Z = -1, 1, 2 do
local Position = Part.CFrame:ToWorldSpace(CFrame.new(X * Part.Size.X / 2, Y * Part.Size.Y / 2, Z * Part.Size.Z / 2)).Position
local ScreenVector, OnScreen = Camera:WorldToViewportPoint(Position)
if OnScreen then
CornerOnScreen = true
break
end
end
if CornerOnScreen then
break
end
end
if CornerOnScreen then
break
end
end
if CornerOnScreen then
local RaycastResult = workspace:Raycast(Camera.CFrame.Position, CFrame.lookAt(Camera.CFrame.Position, Part.Position).LookVector * 1000, Params)
if RaycastResult and RaycastResult.Instance == Part and Part.CFrame.LookVector:FuzzyEq(RaycastResult.Normal) then
FireServer()
workspace.Baseplate.Color = Color3.new(0, 1, 0)
end
else
workspace.Baseplate.Color = Color3.new(1, 0, 0)
end
end
It’s not properly formatted, but this is generally what you’d want.