Check if an object is in the screen

People say I should use camera:WorldToScreenPoint, but I they still return when its in the screen and blocked completely by another part, i thought i should do raycasting but it only returns true when Im looking directly at it, imagine a part in your top left corner of the screen, i want it to load but i have to look directly to it

i want it to load when its in my screen and i can SEE it

4 Likes

does raycasting from the head not work?

1 Like

that would produce the same result as it goes from the head to the object meaning that I have to look directly at it for it to load.

You know what, Ill try to do that

It doesn’t work
my code:

local cloned_block = block:Clone()
					local camera = workspace.CurrentCamera
					local vector, onScreen = camera:WorldToScreenPoint(cloned_block.Position)

					if onScreen then
						local ray = Ray.new(game:GetService("Players").LocalPlayer.Character.Head.Position,cloned_block.Position)
						local hit = workspace:FindPartOnRayWithIgnoreList(ray,game:GetService("Players").LocalPlayer.Character:GetDescendants())

						if hit then
							cloned_block.CFrame = CFrame.new(x*grid,y*grid,z*grid)
							cloned_block.Parent = workspace.terrain
						end	
					end	
1 Like

Maybe this is what you were looking for?

2 Likes

I am going to try that solution, thank you

It doesn’t work sadly :frowning:

					local cloned_block = block:Clone()
					local camera = workspace.CurrentCamera
					local partToCheck = cloned_block

					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, game.Players.LocalPlayer.Character}
					local raycastResult = workspace:Raycast(ray.Origin, ray.Direction * 1000, raycastParams)

					local isVisible = onScreen and not raycastResult
					if isVisible then
						cloned_block.CFrame = CFrame.new(x*grid,y*grid,z*grid)
						cloned_block.Parent = workspace.terrain
					end	

It’s not working because you never set the parent of cloned_block, which means that it will never be visible.

local _, OnScreen = workspace.CurrentCamera:WorldToScreenPoint(ObjectPosition)

if OnScreen then
    if #workspace.CurrentCamera:GetPartsObscuringTarget({workspace.CurrentCamera.CFrame.Position,Object.Position},{Object}) == 0 then
       -- its on screen and its not obstructed
    end
end

This does not detect Transparent parts

21 Likes

you can use :Dot() for the head instead of raycasting

1 Like
local Part = workspace.Look -- This is the part I want this script to check if is visible
local Camera = workspace.Camera
local Character = game:GetService('Players').LocalPlayer.Character

local RunService = game:GetService('RunService')

local Parameters = RaycastParams.new()
Parameters.FilterDescendantsInstances = {Character, Part}
Parameters.FilterType = Enum.RaycastFilterType.Blacklist

RunService.RenderStepped:Connect(function()
	local Vector, OnScreen = Camera:WorldToViewportPoint(Part.Position)

	if OnScreen then
		if workspace:Raycast(Camera.CFrame.Position, Part.Position - Camera.CFrame.Position, Parameters) == nil then
			warn('Part is Onscreen')
		end
	end
	
end)

The downside to this method is that it will detect transparent parts (but maybe you would want that). I can not compare my script with FartFella’s because his script would not work. Although this method does detect transparent parts, I believe it still may be better because you can have a for loop loop through the workspace and add any parts that have a targeted transparency. (For example, I may use a for loop to make the ray not detect any parts that have a transparency more than 0.5.)

By the way, Ray.new is old so I suggest you to learn the newer more accurate/faster workspace:Raycast( )

5 Likes

Can you make this work for transparency 1 parts?

llocal function IsObjectVisible(Object: BasePart)
	local ObjectPosition = Object.Position

	local Players = game:GetService("Players")
	local Player = Players.LocalPlayer

	local Camera = workspace.CurrentCamera
	local Character = Player.Character

	local CameraPosition = Camera.CFrame.Position

	local Position = (CameraPosition + ObjectPosition) * 0.5
	local Diff = (CameraPosition - ObjectPosition)

	local _, OnScreen = Camera:WorldToScreenPoint(ObjectPosition)
	local Params = OverlapParams.new()
	Params.FilterDescendantsInstances = {Character, Object}

	local BoundBox = workspace:GetPartBoundsInBox(CFrame.new(Position, Position + Diff.Unit), Vector3.zAxis * Diff.Magnitude, Params)

	return OnScreen and #BoundBox == 0
end

Edit1: Oops give me a second found a bug
Edit2: Fixed

1 Like

What would this return out of the function? if the part wasn’t obstructed, to save time

This function returns either true or false

1 Like

fartsmella knows how to code, thats wsp