Hi, I need some help. I need to make it so that players locally can’t see objects they don’t see. To do this, I have written functions to check what a player can and cannot see. There is a problem: some parts start to flicker and I don’t know how to fix it. According to my logic everything should work properly. Please help.
local function isPointInView(position)
local characterToPosition = (position - humanoidRootPart.Position).Unit
local forwardVector = humanoidRootPart.CFrame.LookVector
local dotProduct = forwardVector:Dot(characterToPosition)
local angle = math.acos(dotProduct) * (180 / math.pi)
-- Минимальное и максимальное расстояние для видимости объекта
local minDistance = 5 -- Минимальное расстояние для видимости объекта
local distanceToObject = (position - humanoidRootPart.Position).Magnitude
-- Если объект на очень близком расстоянии (меньше minDistance), то он всегда видим
if distanceToObject <= minDistance then
return true
end
-- Проверяем, что объект в пределах угла обзора и на подходящем расстоянии
if angle <= fieldOfView / 2 and distanceToObject <= visibilityDistance then
-- Проверка на наличие препятствий
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {humanoidRootPart.Parent} -- Игнорируем персонажа игрока
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
local rayOrigin = humanoidRootPart.Position
local rayDirection = (position - humanoidRootPart.Position)
local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)
-- Если луч пересёк объект, проверяем его прозрачность
if raycastResult and raycastResult.Instance then
local hitPart = raycastResult.Instance
-- Если объект не является прозрачным, то он блокирует видимость
if hitPart:IsA("BasePart") and hitPart.Transparency == 0 then
return false -- Непрозрачное препятствие, объект не виден
end
end
-- Если объект не пересекается с прозрачными объектами, считаем его видимым
return true
end
return false
end
local function updateBlindZonesAndRoofs()
for _, object in pairs(workspace:GetDescendants()) do
if object:IsA("BasePart") then
if CollectionService:HasTag(object, "AlwaysVisible") then
-- Если объект всегда видим, ничего не меняем
elseif CollectionService:HasTag(object, "AlwaysInvisible") then
object.Transparency = 1 -- Объект всегда скрыт
else
local isVisible = isPointInView(object.Position)
if isVisible then
object.Transparency = 0 -- Объект видим
else
object.Transparency = 1 -- Объект скрыт
end
-- Теперь ищем декали внутри BasePart и делаем их невидимыми
for _, child in pairs(object:GetChildren()) do
if child:IsA("Decal") then
child.Transparency = object.Transparency
end
end
end
end
end
local proximityThreshold = 15 -- Расстояние для приближения
for _, model in pairs(workspace.Buildings:GetChildren()) do
if model:IsA("Model") and model:FindFirstChild("Roof") then
local roof = model:FindFirstChild("Roof")
-- Получаем границы всей крыши как модели
local roofCFrame, roofSize = roof:GetBoundingBox()
-- Определяем минимальные и максимальные границы
local roofMin = Vector3.new(
roofCFrame.Position.X - roofSize.X / 2,
-10000, -- Игнорируем Y
roofCFrame.Position.Z - roofSize.Z / 2
)
local roofMax = Vector3.new(
roofCFrame.Position.X + roofSize.X / 2,
10000, -- Игнорируем Y
roofCFrame.Position.Z + roofSize.Z / 2
)
-- Проверяем, находится ли игрок рядом с крышей
local isNearby = humanoidRootPart.Position.X > (roofMin.X - proximityThreshold) and humanoidRootPart.Position.X < (roofMax.X + proximityThreshold) and
humanoidRootPart.Position.Z > (roofMin.Z - proximityThreshold) and humanoidRootPart.Position.Z < (roofMax.Z + proximityThreshold)
-- Если игрок близко, делаем всю крышу прозрачной
if isNearby then
for _, part in pairs(roof:GetDescendants()) do
if part:IsA("BasePart") or part:IsA("Texture") then
part.Transparency = 1 -- Прозрачный
end
end
else
-- Если игрок не рядом, проверяем видимость
for _, part in pairs(roof:GetDescendants()) do
if part:IsA("BasePart") then
local isVisible = isPointInView(part.Position)
if isVisible then
part.Transparency = 0 -- Полностью видимый
else
part.Transparency = 1 -- Полностью скрытый
end
end
end
end
end
end
end
Full code here:
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local character = game.Players.LocalPlayer.Character
local head = character:FindFirstChild("Head")
local humanoidRootPart = character:FindFirstChild("HumanoidRootPart")
local distance = script.DistanceFromHead.Value
local CollectionService = game:GetService("CollectionService")
wait(0.5)
while not game.Players.LocalPlayer.Character:FindFirstChild("Head") do wait() end
local cam = workspace.CurrentCamera
cam.CameraType = "Scriptable"
local debug = false
local fieldOfView = 90 -- Угол обзора в градусах
local visibilityDistance = 35 -- Дистанция видимости
local function setRoofTransparency(roof, transparency)
for _, part in pairs(roof:GetDescendants()) do
if part:IsA("BasePart") then
part.Transparency = transparency
end
end
end
local function isPointInView(position)
local characterToPosition = (position - humanoidRootPart.Position).Unit
local forwardVector = humanoidRootPart.CFrame.LookVector
local dotProduct = forwardVector:Dot(characterToPosition)
local angle = math.acos(dotProduct) * (180 / math.pi)
-- Минимальное и максимальное расстояние для видимости объекта
local minDistance = 5 -- Минимальное расстояние для видимости объекта
local distanceToObject = (position - humanoidRootPart.Position).Magnitude
-- Если объект на очень близком расстоянии (меньше minDistance), то он всегда видим
if distanceToObject <= minDistance then
return true
end
-- Проверяем, что объект в пределах угла обзора и на подходящем расстоянии
if angle <= fieldOfView / 2 and distanceToObject <= visibilityDistance then
-- Проверка на наличие препятствий
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {humanoidRootPart.Parent} -- Игнорируем персонажа игрока
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
local rayOrigin = humanoidRootPart.Position
local rayDirection = (position - humanoidRootPart.Position)
local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)
-- Если луч пересёк объект, проверяем его прозрачность
if raycastResult and raycastResult.Instance then
local hitPart = raycastResult.Instance
-- Если объект не является прозрачным, то он блокирует видимость
if hitPart:IsA("BasePart") and hitPart.Transparency == 0 then
return false -- Непрозрачное препятствие, объект не виден
end
end
-- Если объект не пересекается с прозрачными объектами, считаем его видимым
return true
end
return false
end
local function updateBlindZonesAndRoofs()
for _, object in pairs(workspace:GetDescendants()) do
if object:IsA("BasePart") then
if CollectionService:HasTag(object, "AlwaysVisible") then
-- Если объект всегда видим, ничего не меняем
elseif CollectionService:HasTag(object, "AlwaysInvisible") then
object.Transparency = 1 -- Объект всегда скрыт
else
local isVisible = isPointInView(object.Position)
if isVisible then
object.Transparency = 0 -- Объект видим
else
object.Transparency = 1 -- Объект скрыт
end
-- Теперь ищем декали внутри BasePart и делаем их невидимыми
for _, child in pairs(object:GetChildren()) do
if child:IsA("Decal") then
child.Transparency = object.Transparency
end
end
end
end
end
local proximityThreshold = 15 -- Расстояние для приближения
for _, model in pairs(workspace.Buildings:GetChildren()) do
if model:IsA("Model") and model:FindFirstChild("Roof") then
local roof = model:FindFirstChild("Roof")
-- Получаем границы всей крыши как модели
local roofCFrame, roofSize = roof:GetBoundingBox()
-- Определяем минимальные и максимальные границы
local roofMin = Vector3.new(
roofCFrame.Position.X - roofSize.X / 2,
-10000, -- Игнорируем Y
roofCFrame.Position.Z - roofSize.Z / 2
)
local roofMax = Vector3.new(
roofCFrame.Position.X + roofSize.X / 2,
10000, -- Игнорируем Y
roofCFrame.Position.Z + roofSize.Z / 2
)
-- Проверяем, находится ли игрок рядом с крышей
local isNearby = humanoidRootPart.Position.X > (roofMin.X - proximityThreshold) and humanoidRootPart.Position.X < (roofMax.X + proximityThreshold) and
humanoidRootPart.Position.Z > (roofMin.Z - proximityThreshold) and humanoidRootPart.Position.Z < (roofMax.Z + proximityThreshold)
-- Если игрок близко, делаем всю крышу прозрачной
if isNearby then
for _, part in pairs(roof:GetDescendants()) do
if part:IsA("BasePart") or part:IsA("Texture") then
part.Transparency = 1 -- Прозрачный
end
end
else
-- Если игрок не рядом, проверяем видимость
for _, part in pairs(roof:GetDescendants()) do
if part:IsA("BasePart") then
local isVisible = isPointInView(part.Position)
if isVisible then
part.Transparency = 0 -- Полностью видимый
else
part.Transparency = 1 -- Полностью скрытый
end
end
end
end
end
end
end
local redSphere = Instance.new("Part")
redSphere.Shape = Enum.PartType.Ball
redSphere.Color = Color3.new(1, 0, 0)
redSphere.Material = Enum.Material.Neon
redSphere.Size = Vector3.new(0.2, 0.2, 0.2)
redSphere.Anchored = true
redSphere.CanCollide = false
redSphere.Parent = workspace
if not debug then
redSphere:Destroy()
end
local offsetY = -57
local function checkAndSetRoofTransparency()
local proximityThreshold = 15 -- Расстояние для приближения
for _, model in pairs(workspace.Buildings:GetChildren()) do
if model:IsA("Model") and model:FindFirstChild("Roof") then
local roof = model:FindFirstChild("Roof")
local roofCFrame, roofSize = roof:GetBoundingBox()
local roofMin = roofCFrame.Position - roofSize / 2
local roofMax = roofCFrame.Position + roofSize / 2
local isNearby = humanoidRootPart.Position.X > (roofMin.X - proximityThreshold) and humanoidRootPart.Position.X < (roofMax.X + proximityThreshold) and
humanoidRootPart.Position.Z > (roofMin.Z - proximityThreshold) and humanoidRootPart.Position.Z < (roofMax.Z + proximityThreshold) and
humanoidRootPart.Position.Y < (roofMax.Y + proximityThreshold)
if isNearby then
setRoofTransparency(roof, 1) -- Прозрачный
else
setRoofTransparency(roof, 0) -- Полностью видимый
end
end
end
end
RunService.Heartbeat:Connect(function()
cam.CFrame = CFrame.new(Vector3.new(head.Position.X - 0.001, head.Position.Y + distance, head.Position.Z), head.Position)
local mouseLocation = UserInputService:GetMouseLocation()
local ray = cam:ScreenPointToRay(mouseLocation.X, mouseLocation.Y + offsetY)
local groundY = 0
local distanceToGround = (head.Position.Y - groundY) / -ray.Direction.Y
local groundPosition = ray.Origin + ray.Direction * distanceToGround
if debug then
redSphere.Position = groundPosition
end
local characterPosition = Vector3.new(humanoidRootPart.Position.X, groundY, humanoidRootPart.Position.Z)
local directionToCursor = (groundPosition - characterPosition).Unit
humanoidRootPart.CFrame = CFrame.new(humanoidRootPart.Position, humanoidRootPart.Position + Vector3.new(directionToCursor.X, 0, directionToCursor.Z))
updateBlindZonesAndRoofs()
--checkAndSetRoofTransparency()
end)