How do I cast a ray from one object to another using cframe/vector3 angular math?

  1. What do you want to achieve? To create a zombie mob that can detect whether or not it can see the player, using raycasting and checking if the zombie’s head shooting a ray into the other players head, hits the players head, or hits an obstacle so that the zombie does not have esp and see the player through walls.

  2. What is the issue? I cannot seem to wrap my head around getting the ray to cast towards the other brick, the vector 3 values are confusing to me and the angle math and rotation radians I can’t seem to quite grasp even after searching extensively through the forums at 20 different articles.
    Lookvector is not a solution and a lot of other things aren’t either. I tried seeing if I can rotate the brick with my values as well, but I can’t figure out how to do that.

  3. What solutions have you tried so far? I have looked extensively through the developer hug, but the questions I looked up didn’t seem to have a similar problem. Perhaps I’m not searching for the correct keywords. As far as I know, raycasting is the best way to do this, perhaps there’s a better way but this is the only one I can think of.

here is my script

local originc = game.Workspace.projector.CFrame
-- the block that sends the raycast
local targetc = game.Workspace.targeter.CFrame
-- block that theoretically receives said raycast
local y1 = originc.Y
local y2 = targetc.Y
local x1 = originc.X
local x2 = targetc.X
local z1 = originc.Z
local z2 = targetc.Z
-- listing Xyz values

local angleofattacky = math.atan2(y1 - y2, x1 - x2)
local angleofattackxz = math.atan2(x1 - x2, z1 - z2)
-- doing math to figure out angles
print(angleofattackxz.. "zx angle")
print(angleofattacky.. "yx angle")

originc = originc * CFrame.Angles(0,angleofattackxz, angleofattacky)

local rayOrigin = script.Parent
	local rayDirection = Vector3.new(0, angleofattackxz, angleofattacky)
 
	
	local raycastParams = RaycastParams.new()
	raycastParams.FilterDescendantsInstances = {script.Parent}
	raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)
 
	if raycastResult then
		local hitPart = raycastResult.Instance
		
	if hitPart.Name == game.Workspace.targeter then
		print("Ray hit part!")
	else
		print("ray did not hit correct part")
	end
	end

keep in mind, I’m not actually trying to make the block rotate, it should not rotate and I’m trying that for testing purposes and will remove it later. This is also the first time I’m working with Vector3 rotational values and subsequently the raycast angles.
ray goes from part one to part 2, but it doesn’t for some reason.

here is a picture:

It would be incredibly helpful for me going forward as a programmer currently learning if someone can explain to me where I’m failing and how to actually do it. Thank you in advance.

3 Likes

Here’s how you would create the ray:
StartPosition is the position you want your ray to start at, lookAt is the position you want your ray to point to (kinda like cframe.new’s second parameter)
Distance is how long you want the ray to be in studs

Fill those out to whatever position / lengths you want and you won’t have to worry about the vector math behind it at all really, but if you do want to understand it a bit let me know.

local originc = game.Workspace.projector.CFrame -- the block that sends the raycast
local targetc = game.Workspace.targeter.CFrame -- block that receives the raycast

local startPosition = originc.Position --position you want the ray to start at
local lookAt = targetc.Position --the position you want your ray to look at
local distance = (startPosition - lookAt).magnitude --how far you want the ray to go (the distance between the two parts)

local ray = Ray.new(startPosition, (lookAt-startPosition).Unit * distance) --creating the ray
19 Likes

So essentially, just lookAt-startPosition?

4 Likes

Thank you, this cleared up a lot of things for me and relieved me of having to deal with advanced math.

local originc = game.Workspace.projector.CFrame
-- the block that sends the raycast
local targetc = game.Workspace.targeter.CFrame
-- block that theoretically receives said raycast

local startPosition = originc.Position --position you want the ray to start at
local lookAt = targetc.Position --the position you want your ray to look at
local distance = (startPosition - lookAt).magnitude --how far you want the ray to go (the distance between the two parts)

local ray = Ray.new(startPosition, (lookAt-startPosition).Unit * distance) --creating the ray

while wait(5) do
local hitPart, hitPosition = workspace:FindPartOnRay(ray, script.Parent)
if hitPart then
	print("Hit part: " .. hitPart:GetFullName())
	if hitPart.Name == "targeter" then
		print("Hit target part! Success!")
	elseif hitPart.Name ~= "targeter" then
		print("hit wrong part")
	end
else
	print("Did not hit part")
	end
	end


worked like a charm!
says it hit when i cast it and when I blocked it, it said it hit the wrong part, exactly how I want it to work, your amazing and I am forever grateful.

Though, if it is not too much, can you explain to me how the vector math works for future reference so I can create Lazers from one point to another using raycast and face one part to another part rotationally? If you can’t its ok, but it would really help me to have this type of resource I can refer to in the future.
Thanks a lot RoyalToe I appreciate it.

4 Likes

You’re making a ray that starts at the start position, then you create a vector that goes from the start position to the end position, but it has a length of 1 stud (endPos - startPos).Unit, then you get the distance between both points and multiply the vector by it, so it has the right length between both positions

1 Like