This is not really possible right now, the best chance you have is Raycasting like @LuauThread said. But, you would need to raycast to every point of the part to see if any point is visible. You could instead raycast from each corner, and the center which would work for most things.
Something like this could work:
local player = game.Players.LocalPlayer
local origins = { -- Center, All corners, all surfaces
Vector3.new(),
Vector3.new(1,1,1),
Vector3.new(1,1,-1),
Vector3.new(-1,1,-1),
Vector3.new(-1,1,1),
Vector3.new(1,-1,1),
Vector3.new(1,-1,-1),
Vector3.new(-1,-1,-1),
Vector3.new(-1,-1,1),
Vector3.new(1,0,0),
Vector3.new(-1,0,0),
Vector3.new(0,1,0),
Vector3.new(0,-1,0),
Vector3.new(0,0,1),
Vector3.new(0,0,-1),
}
local function IsVisible(part, viewer)
local s = part.Size/2
local cf = part.CFrame
local settings = RaycastParams.new()
settings.FilterDescendantsInstances = {part, player.Character}
settings.FilterType = Enum.RaycastFilterType.Blacklist
for _, origin in pairs(origins) do
local spot = (origin * s) + viewer.Position
local direction = spot - viewer.CFrame.Position
local result = workspace:Raycast(viewer.CFrame.Position, direction, settings)
if result then return result end
end
end