Issues with raycasting

This is my first attempt at raycasting. I’m trying to detect if there’s any parts between the player and the NPC. I can’t figure out what’s going wrong here. If there’s a wall there, it still runs it as if it wasn’t there.

        local wallCheck = Ray.new(script.Parent["173Mesh"].CFrame.p,target.CFrame.p)
    	local parts = workspace:FindPartOnRay(wallCheck,script.Parent)
		if(parts) then
			print(parts.Parent.Name.."\t"..parts.Name)
		end
		if(target.CFrame.LookVector:Dot(script.Parent.Torso.CFrame.LookVector) > 0.5) then

			if(not parts or parts.Parent ~= target.Parent or parts.Parent:IsA("Accessory")) then
				-- This always runs, but it's not supposed to.
			else
				-- This should run when there's a wall between the NPC and player, but it doesn't.
			end
		else
			-- Looking at the NPC.
		end
1 Like

The first parameter is where it starts, the second parameter is where it is going:

local wallCheck = Ray.new(script.Parent["173Mesh"].Position, CFrame.new(script.Parent["173Mesh"].Position, target.Position).Unit * (script.Parent.Position - target.Position).Magnitude) 

CFrame.new(script.Parent["173Mesh"].Position, target.Position) returns the look vector needed(so a straight line from the NPC to the player), .Unit converts it to 1 stud in length, then (script.Parent.Position - target.Position).Magnitude just multiplies it by how long it has to be to reach the player.

Edit: The answer to the OP’s original question is at the bottom of this reply.


workspace:Raycast() works in studio now, so you should use that instead.
Here’s an example on how you can use it:

local UserInputService = game:GetService("UserInputService")
local Player = game:GetService("Players").LocalPlayer

local GUI_INSET = Vector2.new(0, 36)
local RANGE = 1e3 -- 10^3
 
local RAYCAST_PARAMS = RaycastParams.new()
RAYCAST_PARAMS.IgnoreWater = false
RAYCAST_PARAMS.FilterDescendantsInstances = {Player.Character or Player.CharacterAdded:Wait()}
RAYCAST_PARAMS.FilterType = Enum.RaycastFilterType.Blacklist
 
local function get3DPosition()
    local screenPosition = UserInputService:GetMouseLocation() - GUI_INSET
    local oray = Camera:ScreenPointToRay(screenPosition.X, screenPosition.Y, 0)
    return workspace:Raycast(oray.Origin, oray.Direction * RANGE, RAYCAST_PARAMS)
end

Player.CharacterAdded:Connect(function(character)
    RAYCAST_PARAMS.FilterDescendantsInstances[1] = character
end)

-- how you get each item:
local raycastResult = get3DPosition()
if raycastResult then
    -- it's nil if it doesn't hit a part
    local part = raycastResult.Instance
    local pos = raycastResult.Position
    local normal = raycastResult.Normal
end

Source: (run this in the command bar)

print(not not workspace.Raycast)

This prints true if the function exists, and false if it doesn’t. You can use the same method to check other functions as well. (the not not has a functional purpose.)


Firstly, .p is deprecated so you should use .Position instead.

Now, to actually solve your raycasting issue. The reason it didn’t work is because the second parameter of Ray.new() is the direction, not the end position.

To create a Vector3 direction with the end position, you have to do this:

local startPosition = script.Parent["173Mesh"].CFrame.Position
local endPosition = target.CFrame.Position

local ray = Ray.new(startPosition, (endPosition - startPosition))

The (endPosition - startPosition) is what the direction portion (the second parameter of) your Ray.new() should be.

Again, I recommend using workspace:Raycast() though.

1 Like

CFrame.new(pos, look) returns a CFrame, not a Vector3, so you can’t just use .Unit on it. Instead, you have to do cframe.LookVector (cframe is the result from CFrame.new(pos, look)), and LookVector is already a UnitVector so you don’t need to use.Unit on it after that.


Also, CFrame.new(pos, look) is actually deprecated, Source:


Instead, you should use CFrame.fromMatrix():

function lookAt(pos, look)
    local forwardVector = (pos - look).Unit
    local rightVector = forwardVector:Cross(Vector3.new(0, 1, 0))
    local upVector = rightVector:Cross(forwardVector)
    return CFrame.fromMatrix(pos, rightVector, upVector)
end
1 Like