function raycast(U,C,y,L)local v,e,P=raycastRecursive(U,C,y,L,y.unit,dot(C,y.unit))if dot(e,y)>0 then e=-e end return v,C+P*y,e.unit,P end function raycastRecursive(U,C,y,L,v,e)if U.className=="\080\097\114\116"or U.className=="\083\101\097\116"or U.className=="\083\112\097\119\110\076\111\099\097\116\105\111\110"then local P=U.Size.magnitude/2 local i=dot(U.Position,v)-e if i+P>0 and(i-P<y.magnitude and(((i*v+C)-U.Position).magnitude<P and L(U)))then local L=U.Size/2 if U.Shape==Enum.PartType.Ball then local v,e=getLineSphereCollide(C,y,U.Position,L.x)if v<1 and v>=0 then return U,(v*y+C)-U.Position,v else return nil,Vector3.new(0,0,0),1 end elseif U.Shape==Enum.PartType.Block then local v=1 local e=U.CFrame-U.Position local P=e*Vector3.new(1,0,0)local i=e*Vector3.new(0,1,0)local p=e*Vector3.new(0,0,1)local X=-dot(P,y)local h=-dot(i,y)local B=-dot(p,y)local F,I,l,d,x,a=-1 local s=dot(P,C-U.Position)if X~=0 then F=(s-L.x)/X I=(s+L.x)/X if I<F then local U=F F=I I=U end else if math.abs(s)<L.x then I=1 F=0 else return nil,Vector3.new(0,0,0),1 end end local w=dot(i,C-U.Position)if h~=0 then l=(w-L.y)/h d=(w+L.y)/h if d<l then local U=l l=d d=U end else if math.abs(w)<L.y then d=1 l=0 else return nil,Vector3.new(0,0,0),1 end end local G=dot(p,C-U.Position)if B~=0 then x=(G-L.z)/B a=(G+L.z)/B if a<x then local U=x x=a a=U end else if math.abs(G)<L.z then a=1 x=0 else return nil,Vector3.new(0,0,0),1 end end if F<=d and(I>=l and(F<=a and(I>=x and(x<=d and a>=l))))then local C=P local y=F if l>y then y=l C=i end if x>y then y=x C=p end if y>=0 and y<1 then v=y elseif I>0 and(d>0 and(a>0 and y<0))then v=0 C=Vector3.new(0,0,0)end return U,C,v else return nil,Vector3.new(0,0,0),1 end else local v=1 local e=U.CFrame-U.Position local P=e*Vector3.new(1,0,0)local i=-dot(P,y)local p,X=-1 local h=dot(P,C-U.Position)if i~=0 then p=(h-L.x)/i X=(h+L.x)/i if X<p then local U=p p=X X=U end else if math.abs(h)<L.x then X=1 p=0 else return nil,Vector3.new(0,0,0),1 end end local B=e:pointToObjectSpace(y)*Vector3.new(0,1,1)local F=U.CFrame:pointToObjectSpace(C)*Vector3.new(0,1,1)local I,l=getLineSphereCollide(F,B,Vector3.new(0,0,0),L.y)if p<=l and(X>=I and l>0)then local C=P local y=p if I>y then y=I C=e*(F+B*y)end if y>=0 and y<1 then v=y elseif X>0 and(l>0 and y<0)then v=0 C=Vector3.new(0,0,0)end return U,C,v else return nil,Vector3.new(0,0,0),1 end return nil,Vector3.new(0,0,0),1 end end return nil,Vector3.new(0,0,0),1 elseif U.className=="\077\111\100\101\108"or U.className=="\087\111\114\107\115\112\097\099\101"or U.className=="\072\097\116"or U.className=="\084\111\111\108"then local P=U:GetChildren()local i=1 local p=Vector3.new(0,0,0)local X=nil for U=1,#P,1 do if P[U]~=nil then local h,B,F=raycastRecursive(P[U],C,y,L,v,e)if F<i then i=F X=h p=B end end end return X,p,i else return nil,Vector3.new(0,0,0),1 end end
--Returns hit, position, normal, time
function raycast(model, start, vector, brickFunction)
	local hit, normal, time =
		raycastRecursive(model, start, vector, brickFunction, vector.unit, dot(start, vector.unit))
	if dot(normal, vector) > 0 then
		normal = -normal
	end
	return hit, start + time * vector, normal.unit, time
end
function raycastRecursive(model, start, vector, brickFunction, unitVec, startDist)
	if (model.className == "Part") or (model.className == "Seat") or (model.className == "SpawnLocation") then
		local range = model.Size.magnitude / 2
		local dist = dot(model.Position, unitVec) - startDist
		if
			(dist + range > 0)
			and (dist - range < vector.magnitude)
			and ((dist * unitVec + start - model.Position).magnitude < range)
			and brickFunction(model)
		then
			local halfSize = model.Size / 2
			if model.Shape == Enum.PartType.Ball then
				local time, timeMax = getLineSphereCollide(start, vector, model.Position, halfSize.x)
				if (time < 1) and (time >= 0) then
					return model, (time * vector + start - model.Position), time
				else
					return nil, Vector3.new(0, 0, 0), 1
				end
			elseif model.Shape == Enum.PartType.Block then
				local time = 1
				local cf = model.CFrame - model.Position
				local xvec = cf * Vector3.new(1, 0, 0)
				local yvec = cf * Vector3.new(0, 1, 0)
				local zvec = cf * Vector3.new(0, 0, 1)
				local xspd = -dot(xvec, vector)
				local yspd = -dot(yvec, vector)
				local zspd = -dot(zvec, vector)
				local xmin, xmax, ymin, ymax, zmin, zmax = -1
				local dotProd = dot(xvec, start - model.Position)
				if xspd ~= 0 then
					xmin = (dotProd - halfSize.x) / xspd
					xmax = (dotProd + halfSize.x) / xspd
					if xmax < xmin then
						local swap = xmin
						xmin = xmax
						xmax = swap
					end
				else
					if math.abs(dotProd) < halfSize.x then
						xmax = 1
						xmin = 0
					else
						return nil, Vector3.new(0, 0, 0), 1
					end
				end
				local dotProd = dot(yvec, start - model.Position)
				if yspd ~= 0 then
					ymin = (dotProd - halfSize.y) / yspd
					ymax = (dotProd + halfSize.y) / yspd
					if ymax < ymin then
						local swap = ymin
						ymin = ymax
						ymax = swap
					end
				else
					if math.abs(dotProd) < halfSize.y then
						ymax = 1
						ymin = 0
					else
						return nil, Vector3.new(0, 0, 0), 1
					end
				end
				local dotProd = dot(zvec, start - model.Position)
				if zspd ~= 0 then
					zmin = (dotProd - halfSize.z) / zspd
					zmax = (dotProd + halfSize.z) / zspd
					if zmax < zmin then
						local swap = zmin
						zmin = zmax
						zmax = swap
					end
				else
					if math.abs(dotProd) < halfSize.z then
						zmax = 1
						zmin = 0
					else
						return nil, Vector3.new(0, 0, 0), 1
					end
				end
				if
					(xmin <= ymax)
					and (xmax >= ymin)
					and (xmin <= zmax)
					and (xmax >= zmin)
					and (zmin <= ymax)
					and (zmax >= ymin)
				then
					local normal = xvec
					local min = xmin
					if ymin > min then
						min = ymin
						normal = yvec
					end
					if zmin > min then
						min = zmin
						normal = zvec
					end
					if (min >= 0) and (min < 1) then
						time = min
					elseif (xmax > 0) and (ymax > 0) and (zmax > 0) and (min < 0) then
						time = 0
						normal = Vector3.new(0, 0, 0)
					end
					return model, normal, time
				else
					return nil, Vector3.new(0, 0, 0), 1
				end
			else --	Cylinder
				local time = 1
				local cf = model.CFrame - model.Position
				local xvec = cf * Vector3.new(1, 0, 0)
				local xspd = -dot(xvec, vector)
				local xmin, xmax = -1
				local dotProd = dot(xvec, start - model.Position)
				if xspd ~= 0 then
					xmin = (dotProd - halfSize.x) / xspd
					xmax = (dotProd + halfSize.x) / xspd
					if xmax < xmin then
						local swap = xmin
						xmin = xmax
						xmax = swap
					end
				else
					if math.abs(dotProd) < halfSize.x then
						xmax = 1
						xmin = 0
					else
						return nil, Vector3.new(0, 0, 0), 1
					end
				end

				local relVec = cf:pointToObjectSpace(vector) * Vector3.new(0, 1, 1)
				local relPos = model.CFrame:pointToObjectSpace(start) * Vector3.new(0, 1, 1)
				local rmin, rmax = getLineSphereCollide(relPos, relVec, Vector3.new(0, 0, 0), halfSize.y)
				if (xmin <= rmax) and (xmax >= rmin) and (rmax > 0) then
					local normal = xvec
					local min = xmin
					if rmin > min then
						min = rmin
						normal = cf * (relPos + relVec * min)
					end
					if (min >= 0) and (min < 1) then
						time = min
					elseif (xmax > 0) and (rmax > 0) and (min < 0) then
						time = 0
						normal = Vector3.new(0, 0, 0)
					end
					return model, normal, time
				else
					return nil, Vector3.new(0, 0, 0), 1
				end
				return nil, Vector3.new(0, 0, 0), 1
			end
		end
		return nil, Vector3.new(0, 0, 0), 1
	elseif
		(model.className == "Model")
		or (model.className == "Workspace")
		or (model.className == "Hat")
		or (model.className == "Tool")
	then
		local children = model:GetChildren()
		local time = 1
		local normal = Vector3.new(0, 0, 0)
		local hit = nil
		for n = 1, #children do
			if children[n] ~= nil then
				local newHit, newNormal, newTime =
					raycastRecursive(children[n], start, vector, brickFunction, unitVec, startDist)
				if newTime < time then
					time = newTime
					hit = newHit
					normal = newNormal
				end
			end
		end
		return hit, normal, time
	else
		return nil, Vector3.new(0, 0, 0), 1
	end
end
