Raycasting straight up or down is wonky

Note: I know reposting/bumping is technically against the rules but i’ve been trying to fix this for the past day to no avail and am at a total loss. Please help I am going insane

I played a game the other day that had the premise of the LIDAR map from Garry’s Mod and enjoyed the concept, so I thought I’d recreate it myself and maybe put a spin on it. Currently I have the basic system down of raycasting and then placing dots where the rays hit, but when the camera looks straight up or straight down the dots seem to “compress” and the cone gets tighter. Truthfully I don’t fully understand the CFrame math that’s happening and just kinda brute forced it until it worked, so any help would be appreciated.

This is how it’s supposed to look:

This is when the camera is straight up:

This is when the camera is straight down:

And this is the code:

uis.InputBegan:Connect(function(input, gpe)
	if gpe then
		return
	else
		if input.KeyCode == Enum.KeyCode.F and debounce == false then
			debounce = true
			workspace.CurrentCamera.CameraType = Enum.CameraType.Scriptable
			hum.WalkSpeed = 0
			for y = 40, -40, -2 do
				local camera = workspace.CurrentCamera.CFrame
				for x = 80, -80, -2 do
					local lookvector = camera.LookVector
					
					local ranX = math.random(x-1, x)
					local ranY = math.random(y-1, y)
					print((lookvector * 100) + Vector3.new(lookvector.Z * -ranX,ranY,lookvector.X * ranX))
					local rayresult = workspace:Raycast(camera.Position, (lookvector * 100) + Vector3.new(lookvector.Z * -ranX,ranY,lookvector.X * ranX),params)
					-- negative rightvector + position zvector makes it go left
					-- positive rightvector + negative zvector makes it go right
					if rayresult then
						local newdot = dot:Clone()
						newdot.Position = rayresult.Position
						newdot.Parent = workspace.dotholder
						local otherdots = workspace:GetPartsInPart(newdot)
						if #otherdots > 1 then
							destroydots(otherdots, newdot)
						else
							table.insert(ignorelist, dot)
							task.delay(45, newdot.Destroy, newdot)
						end
					end
				end	
				runservice.Heartbeat:Wait(0.5)
			end
			workspace.CurrentCamera.CameraType = Enum.CameraType.Custom
			hum.WalkSpeed = 16
			debounce = false
		end
	end
end)

Extra info:

  • newdot is being cloned from ReplicatedStorage
  • destroydots is a function to make sure the dots don’t overlap, it saves performance since they’re already pretty close together
  • Everything in the character is blacklisted so the rays pass through them

Looking at some Garry’s Mod LIDAR videos (and correct me if I’m wrong), it looks like you just want to scatter dots across the 3d world to give the effect of 2d noise? In this case, you probably just need to use ScreenPointToRay to sample random parts of the screen then slap a dot on top of them?

2 Likes

I love LIDAR games. I hope you put something out eventually!

As for your problem.

You’re very close to the solution. You shouldn’t be using lookVector.Z/X to get your left/right and up/down. You should instead be using CFrame.UpVector and CFrame.RightVector.

This should fix it.

				local lookvector = camera.LookVector
				local upvector = camera.UpVector
				local rightvector = camera.RightVector

				local ranX = math.random(x-1, x)
				local ranY = math.random(y-1, y)
				local rayresult = workspace:Raycast(camera.Position, (lookvector * 100) + ranX * rightvector + ranY * upvector,params)

I agree with this too. This system is currently using a projection from a single point. You will find that the grid is tiny if you hug walls (similar to how you point a flashlight into a wall). This is something that should be taken care of later. You can layer this on top after you fix the rotation issue.

2 Likes

Ohhh I see, using the vectors works perfectly! I’ll also check out the ScreenPointToRay as an alternative if I can get it to work. Thank you very much.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.