Attempting to loop a raycast until it hits something that isn't transparent

So this is very situational, and pretty much not constructive to anyone besides me since I doubt many people will need this kind of thing.

That being said I’m really selfish and am making a post asking for help anyway :slight_smile:

Alright let me get down to the details, here’s the code:

function ProcessTransparency(Raycast, Direction, Color, Params, Origin, PixelToWorldspace, Blocked)
    if Raycast.Instance.Transparency >= 0.01 then
    	local Colors = {{Color, Raycast.Instance.Transparency}} -- Color, Influence
    	local DistLeft = FC.RenderDist
    	local Frame = 0
    	while Raycast do
    		DistLeft = DistLeft - (Origin - Raycast.Position).Magnitude
    		Origin = Raycast.Position
    		local SetColor
    		local Raycast = PerformRaycast(Origin, Direction * DistLeft, Params)
    		if Raycast then
    			SetColor = Raycast.Instance.Color
    			if FC.Materialization then SetColor = ProcessMaterial(Raycast, SetColor) end
    			if FC.Shading then SetColor = ProcessShading(Raycast, SetColor) end
    			if FC.Shadows and Raycast.Instance.CastShadow then SetColor = ProcessShadows(Raycast, SetColor, Params, Blocked) end
    			SetColor = {SetColor, Raycast.Instance.Transparency}
    		else
    			if FC.Skybox then
    				local Position = (CFrame.new(PixelToWorldspace.Position) * CFrame.new(Direction * 100)).Position
	    			local Seed = math.clamp((Position.Y+300)*0.002, 120/255, 1)
	    			SetColor = {Color3.new(Seed - (120/255), Seed - (60/255), Seed), 0}
	    		else
	    			SetColor = {Color3.new(1,1,1), 0}
	    		end
	    	end
	    	Colors[#Colors+1] = SetColor
	    	if SetColor[2] < 0.01 or DistLeft <= 0.1 or Frame == 3 then break end
	    	Frame += 1
		end
    	return AverageColors(Colors)
    else
    	if FC.Materialization then Color = ProcessMaterial(Raycast, Color) end
    	if FC.Shading then Color = ProcessShading(Raycast, Color) end
    	if FC.Shadows and Raycast.Instance.CastShadow then Color = ProcessShadows(Raycast, Color, Params, Blocked) end
    	return Color
    end
end

So this question stems from a project I’ve been sort of working on with other great minds on the subject, it’s all laid out in this post.

The desired result:
Imagine a ray that goes from the camera into a direction on the screen, now obviously that ray will hit something and then stop. I want it to hit something, test if it’s transparent, and if it is then perform another raycast going along the same theoretical line as before, and continue to test if what is hit is transparent or not.

Right now it work with just a single transparent part, and I actually know exactly what the issue is.
When testing it with two back to back transparent parts it will crash, which is why I have that Frame stuff in there, to hard break it.

The issue is that each iteration of this loop or some unknown reason to me changed the direction of the raycast, more specifically, it reverses it. Once hitting the first transparent part it will go forward, then when hitting the second it will reverse and head back toward the camera, then once hitting the same part it hit previously it will reverse once again and hit the other exact same part and so on until roblox detects the loop has ran too long, or until I manually hard break it.

I am positive this is the behavior that’s happening, in my testing I’ve seen in my console the swap back and forth from each part, the behavior I described is 100% what’s going on.

The issue is that I don’t know how the direction is changing, when printing the direction it actually stays fairly static although there is variation of about 0.2 in any axis (which I have no freaking clue why). I’m not able to find any real proof that the direction is being reversed, but I know for a fact that’s what’s happening.

Any chance anyone understands this and possibly has an answer?

It should be running out of DistLeft, correct?

So how is the loop running forever?

Is Raycast.Position always a number?

Interestingly, DistLeft is not running out in the way you think it would.

It is decreasing, but will only break the loop in the case that you’re looking through just 1 transparent object. I haven’t printed anything but my assumption is that there’s something going on with it that I’m not aware of.

I think there’s some behavior that I’m not seeing.

Raycast.Position will only exist so long as Raycast does, the only times Raycast will not exist is when the ray hits nothing.

EDIT:
After doing some testing, I can confirm that DistLeft is decreasing, but only by 1 amount, it will go from FC.RenderDist to FC.RenderDist - Magnitude and stay that was, resulting in DistLeft to not drop to 0.

I WANT TO DIE.

I am so sorry for this post!!!

The issue was this line:

local Raycast = PerformRaycast(Origin, Direction * DistLeft, Params)

making Raycast local and putting it in the while loops scope means it doesn’t persist and therefore will infinite loop.

1 Like