Change "findpartonray" to "raycast"

I have a script that uses a defunct FindPartOnRay,
and to keep away from old code, I want to change it to
Raycast.

  1. Do I have to do this? Can I just leave it the same?
  2. If I do have to do this? can you help?
local tst,_=workspace:FindPartOnRay(Ray.new(t.Torso.Position,(n-t.Torso.Position).Unit*99999),t)--tst sees if ray will hit character, t which is NPC is whitelisted ??

local aim=n+Vector3.new(math.random(-mag*.008,mag*.008),math.random(-mag*.009,mag*.009),math.random(-mag*.1,mag*.1))*(2+math.random())+hum --this decides where bullet lands with some randomness
	
local par,pos=workspace:FindPartOnRay(Ray.new(h.Position,(aim-h.Position).Unit*99999),t)--does actual raycast?


There are 2 instances of find part on ray, and I’ve been looking at the documented “raycast” instruction, and can’t totally figure it out.

Any help appreciated.

1 Like

Raycast returns a table when it hits something so you can just check if it has a table and if it does than do stuff

ex.

local results = workspace:RayCast(args)
if results then
print(results.Instance) -- prints the part that it hit
end
1 Like

Specifically I’m trying to change the following FindPartOnRay statements to Raycasts:

local tst,_=workspace:FindPartOnRay(Ray.new(t.Torso.Position,(n-t.Torso.Position).Unit*99999),t)--tst sees if ray will hit character, t which is NPC is whitelisted ??

and



local aim=n+Vector3.new(math.random(-mag*.008,mag*.008),math.random(-mag*.009,mag*.009),math.random(-mag*.1,mag*.1))*(2+math.random())+hum --this decides where bullet lands with some randomness
	



and

local par,pos=workspace:FindPartOnRay(Ray.new(h.Position,(aim-h.Position).Unit*99999),t)--does actual raycast?

where
aim = a lookvector with some randomness (i think?)
n = cframe.pos of nearest character
t = npc with gun
h= the gun handle position

One part I’m having trouble with, is what is that third parameter in the findpartonray? In both cases it is “t” which is the NPC holding the gun. Is that an ignorelist?

Even the answer to that one question would probably help me a lot. I can code, but this is a bit confusing for me, and I can’t find anything on the API that tellsme what that param does?

thanks

Sorry for the late reply I don’t even know if you’re struggling with this anymore and I don’t know much about the deprecated Raycast only the new one reading the API I can see that it ignores the descendants of an instance
which the character is an instance so it will ignore everything in it.

The new raycast uses a table with all the instances in which the descendants are ignored don’t know if that helps

1 Like

When you do workspace:RayCast() you should also do RaycastParams.new() and put it inside there as the 3rd argument.

1 Like

I made this little conversion demo a while back, which shows how the properties of an old-style raycast fit into the new method:

-- Example Values
local origin = Vector3.new(1, 1, 1)
local direction = Vector3.new(2, 2, 2)
local ignoreDescendantsInstances = workspace.Part
local terrainCellsAreCubes = false
local ignoreWater = true

-- Old Method
local hitObject, intersectionPoint, surfaceNormal, material = workspace:FindPartOnRay(
	Ray.new(
		origin,
		direction
	),
	ignoreDescendantsInstances,
	terrainCellsAreCubes, -- This can't be done with the new raycast
	ignoreWater
)

-- New Method
local rayParams = RaycastParams.new() -- This can be reused/changed for other rays
-- You can decide to use this as a whitelist instead of a blacklist like so:
--rayParams.FilterType = Enum.RaycastFilterType.Whitelist/Blacklist
rayParams.FilterDescendantsInstances = ignoreDescendantsInstances
rayParams.IgnoreWater = ignoreWater

local newRay = workspace:Raycast(origin, direction, rayParams)
local hitObject = newRay.Instance
local intersectionPoint = newRay.Position
local surfaceNormal = newRay.Normal
local material = newRay.Material
-- You can also get the distance between start and origin like so:
--local distance = newRay.Distance

So as an example, the first would become:

-- Old
local tst, _ = workspace:FindPartOnRay(
	Ray.new(
		t.Torso.Position,
		(n - t.Torso.Position).Unit * 99999
	),
	t
)

-- New
local rayParams = RaycastParams.new()
rayParams.FilterDescendantsInstances = t
local rayResult = workspace:Raycast(t.Torso.Position, (n - t.Torso.Position).Unit * 99999, rayParams)

And just as a side note, I would recommend using more descriptive variable names, it’s hard to keep track of what n and t and so forth are, but remembering nearestCharacterPos and gunNpc is much easier.

2 Likes

thank you, through trial and error (and the hints from ortacise (yourself) about the table, I did figure it out. I posted what the code looks like in a response below just in case someone else needs it. I did this because they might encounter the same issue (they have a bot that uses “findpartonray” and want to change it to “raycast”.

thank you very much. people on here whom try to help are awesome!

thank you very much for helping. I had figured this out before you responded, but i super appreciate that you went through this trouble.

As far as the variables go, this isn’t my code. I use super-descriptive variables, and I agree with you and appreciate the tip. I really appreciate the trouble you went through in your response. Thank you.

1 Like

For anyone reading this because they are trying to convert some code with “find part on ray” into the more preferred “raycast” I changed my code to look like this:

while true do
--n=CFrame of character within listd distance of NPC
--mag=the distance limit
--hum=look vector that looks at  where the player character was when "near"
	local n,mag,hum=near()--calls near function and that functions sets n,mag,hum
	if n then --if a character was near, and CFrame was sent
		n=n.p--takes position from cFrame without rotational info
		if not r then --r is reload debounce, and false means not reloading at moment

---
-- Build a "RaycastParams" object
local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
raycastParams.FilterDescendantsInstances = {t}--probably t
raycastParams.IgnoreWater = true
---

			w=.0001 --w as wait time is reset (this is global)
			local dir=h.Position-n--h is NPC gun, n is character cframe

			local rayCastTest = workspace:Raycast(t.Torso.Position,(n-t.Torso.Position).Unit*99999, raycastParams)

			local aim=n+Vector3.new(math.random(-mag*.008,mag*.008),math.random(-mag*.009,mag*.009),math.random(-mag*.1,mag*.1))*(2+math.random())+hum --this decides where bullet lands with some randomness
			if rayCastTest and rayCastTest.Instance and rayCastTest.Instance.Parent and game.Players:GetPlayerFromCharacter(rayCastTest.Instance.Parent)then--checks to see if part that was hit by ray was the character's part
				wait(0.4)-- between shots?
				h.Fire:Play()--plays gunsound from gun
				local rayCastReal = workspace:Raycast(h.Position,(aim-h.Position).Unit*99999, raycastParams)

				if rayCastReal and rayCastReal.Instance then--raycast was succesful
					local h=rayCastReal.Instance.Parent:FindFirstChild'Humanoid'or rayCastReal.Instance.Parent.Parent:FindFirstChild'Humanoid'--h is humanoid of character hit
					if h and h.Health-10>0 then--do damage if character won't die
						h.Health=h.Health-10
					elseif h then--character has less health than damage so kill it
						h.Health=0
						h.Parent:BreakJoints()
						
					end
				end
				if rayCastReal and rayCastReal.Instance then	
					ammo=ammo-1--reduce ammo for shot
					mag=(h.Position-rayCastReal.Instance.Position).magnitude--distance between character humanoid and NPC (t)
					b1.Parent,b2.Parent=t,t--parents bullets to npc
					b1.CFrame,b2.CFrame=CFrame.new(h.Position:Lerp(rayCastReal.Instance.Position,.375),rayCastReal.Instance.Position),CFrame.new(rayCastReal.Instance.Position:Lerp(h.Position,.125),h.Position)--lerps bullets to character
					b1.Mesh.Scale,b2.Mesh.Scale=Vector3.new(.2,.2,mag*.75),Vector3.new(.2,.2,mag/4)--changes appearance of bullets?
					delay(.03,function()b1.Parent=nil wait(.03)b2.Parent=nil end)--removes bullets

				end
			end
			wait(.05)
			if ammo==0 then
				reload()--calls reload but doesn't pass "true" ?? so is then "false" and doesn't reload?
			end
		end
	else
		reload(true) --whys it call reload if no "n" cframe?
		w=false --why is w now a boolean?
	end
end

Sorry if its at all hard to understand. I thought I should post the solution in case it helps someone. Thanks again to all respondents - super appreciated. The tip that raycast is returning a table, and I should print the results of that table, was the tip that allowed me to work and finagle it until it works.

Much thanks to Ortacise, Sanguine-Saracen/Bobbybob2131, and Allanv2/alliedoeihoialt !!