-
What do you want to achieve?
Culling algorythm, hiding blocks that the player cannot see. -
What is the issue?
Traces are hiding blocks that should be visible and unobstructed. -
What solutions have you tried so far?
Implementing rigorous debugging, including showing the traces.
Place (can be opened in Studio): Culling - Roblox
Create a model, name it “CULL”, fill it with parts. (ie house with parent model named CULL)
This script is a local script, insert it into StarterCharacterScripts.
local rayOrigin = Vector3.new(0,0,0)
local rayDirection = Vector3.new(0,-100,0)
local raycastParams = RaycastParams.new()
local PL:Model = script.Parent
local C:Camera = workspace.CurrentCamera
local H:Part = PL:WaitForChild("Head")
local CULL = workspace:WaitForChild("CULL")
local DBG_Col_Fast = Color3.new(1,1,1)
local DBG_Col_NoRay = Color3.new(0,0,0)
local DBG_Col_CT = Color3.new(1,0,1)
local DBG_Col_CT_OB = Color3.new(1,1,0)
local Debris:Debris = game:GetService("Debris")
local DBG_SZ = Vector3.new(1,1,1)
task.wait(1) -- Short delay to wait for model & player to be loaded
local TBC = CULL:GetChildren() -- Get all children of the model to be culled.
local function Check_Aggressive(PP:Vector3,v:BasePart)
local cf:CFrame = v.CFrame
local szd = v.Size/2
local szx:number = szd.X;local szy:number = szd.Y;local szz:number = szd.Z;
do
--[[
PPP 7
NPP 2
PNP 4
PPN 6
NNP 8
PNN 5
NPN 1
NNN 3
]]
local R = workspace:Raycast(PP,(cf*CFrame.new(-szx,szy,-szz).Position)-PP,raycastParams)
if (R ~= nil) and (R.Instance == v) then
v.Transparency = 0
--v.Color = DBG_Col_CT
else
R = workspace:Raycast(PP,(cf*CFrame.new(-szx,szy,szx).Position)-PP,raycastParams)
if (R ~= nil) and (R.Instance == v) then
v.Transparency = 0
--v.Color = DBG_Col_CT
else
R = workspace:Raycast(PP,(cf*CFrame.new(-szd).Position)-PP,raycastParams)
if (R ~= nil) and (R.Instance == v) then
v.Transparency = 0
--v.Color = DBG_Col_CT
else
R = workspace:Raycast(PP,(cf*CFrame.new(szx,-szy,szz).Position)-PP,raycastParams)
if (R ~= nil) and (R.Instance == v) then
v.Transparency = 0
--v.Color = DBG_Col_CT
else
R = workspace:Raycast(PP,(cf*CFrame.new(szx,-szy,-szz).Position)-PP,raycastParams)
if (R ~= nil) and (R.Instance == v) then
v.Transparency = 0
--v.Color = DBG_Col_CT
else
R = workspace:Raycast(PP,(cf*CFrame.new(szx,szy,-szz).Position)-PP,raycastParams)
if (R ~= nil) and (R.Instance == v) then
v.Transparency = 0
--v.Color = DBG_Col_CT
else
R = workspace:Raycast(PP,(cf*CFrame.new(szd).Position)-PP,raycastParams)
if (R ~= nil) and (R.Instance == v) then
v.Transparency = 0
--v.Color = DBG_Col_CT
else
R = workspace:Raycast(PP,(cf*CFrame.new(-szx,-szy,szz).Position)-PP,raycastParams)
if (R ~= nil) and (R.Instance == v) then
v.Transparency = 0
--v.Color = DBG_Col_CT
else
v.Transparency = 1
--v.Color = DBG_Col_CT_OB
end
end
end
end
end
end
end
end
end
end
local PP:Vector3;
local OP:OverlapParams;
do
raycastParams.FilterType = Enum.RaycastFilterType.Exclude
raycastParams.RespectCanCollide = true
raycastParams.IgnoreWater = true
task.wait(1)
raycastParams.FilterDescendantsInstances = {PL}
end
--[[do
OP = OverlapParams.new()
OP.FilterType = Enum.RaycastFilterType.Exclude
OP.FilterDescendantsInstances = {PL}
OP.MaxParts = 25
OP.BruteForceAllSlow = false
OP.RespectCanCollide = true
end]]
local function FastCull(PP,v)
--[[local VP = v.Position
OP.FilterDescendantsInstances = {PL,v}
local GPIP = workspace:GetPartBoundsInRadius(VP,v.Size.Magnitude,OP)
if (GPIP ~= nil) and (#GPIP > 0) then
table.insert(GPIP,PL)
raycastParams.FilterDescendantsInstances = GPIP
else
raycastParams.FilterDescendantsInstances = {PL}
end]]
local r:RaycastResult = workspace:Raycast(PP,(v.Position-PP),raycastParams)
if (r ~= nil) then
local i = r.Instance
if (i ~= v) then
return v
else
v.Transparency = 0
--v.Color = DBG_Col_Fast
end
--[[else
task.wait()
warn("NORAY")
v.Color = DBG_Col_NoRay
return v]]
end
end
local CLIP_Z:number = 2000
while (CULL ~= nil) and (C ~= nil) do
task.wait(.1)
local PP:Vector3;
local CF:CFrame = C.CFrame
local CFP:Vector3 = CF.Position
local CullFourthPass = {}
do
local CullFirstPass = {}
for k,v:BasePart in pairs(TBC) do
if ((CFP-v.Position).Magnitude <= CLIP_Z) then
table.insert(CullFirstPass,v)
else
v.Transparency = 1
end
end
local CullSecondPass = {}
PP = H.Position
for k,v:BasePart in pairs(CullFirstPass) do
local Ret:BasePart? = FastCull(PP,v)
if (Ret ~= nil) then
table.insert(CullSecondPass,Ret)
end
end
task.wait()
local CullThirdPass = {}
do
local CP = CFP-(CF.LookVector*100)
PP = Vector3.new(math.floor(CP.X*10)/10,math.floor(CP.Y*10)/10,math.floor(CP.Z*10)/10)
end
for k,v:BasePart in pairs(CullSecondPass) do
local Ret:BasePart? = FastCull(PP,v)
if (Ret ~= nil) then
table.insert(CullThirdPass,Ret)
end
end
task.wait()
do
local CP = CFP-(CF.LookVector*10)
PP = Vector3.new(math.floor(CP.X*10)/10,math.floor(CP.Y*10)/10,math.floor(CP.Z*10)/10)
end
for k,v:BasePart in pairs(CullThirdPass) do
local Ret:BasePart? = FastCull(PP,v)
if (Ret ~= nil) then
table.insert(CullFourthPass,Ret)
end
end
end
task.wait()
local CullFinalPass = {}
do
local CP:Vector3 = CFP
PP = Vector3.new(math.floor(CP.X*10)/10,math.floor(CP.Y*10)/10,math.floor(CP.Z*10)/10)
end
for k,v in pairs(CullFourthPass) do
local Ret:BasePart? = FastCull(PP,v)
if (Ret ~= nil) then
task.delay(k/10000,Check_Aggressive,PP,Ret)
end
end
end