Find an angle between 2 vector 3's and then shoot a raycast using that angle

Okay I’m a bit confused now. Are you looking to make a block placement thing or are you looking to place blocks automatically in a line in front of the player? If you’re looking for block placement you could just use the normal property of the raycast result to snap a part to another part’s face, which would be the face that the mouse hits.

For example,

local ray = workspace:Raycast(mouse.Origin, mouse.Direction * 1000)
if ray then
    local normal = ray.Normal
    local instance = ray.Instance
    newBlock.CFrame = instance.CFrame * CFrame.new(normal * (instance.Size / 2 + blockSize / 2))
end

im trying to detect if there is a block there so i can build infront of that block like a line infront of the player as you said

Okay then in that case you should be able to use this:

You can still get the goal position by using the position variable, you’d just need to change the Y axis to be grid aligned and actually below the player instead of level to the player.

i already know where the player is and where the block is suppost to be so i want to check that 1 position not increment the raycast my 1 untill it detects no block there

Okay, if you know the position the block is supposed to be, why can’t you just cast the ray there to check that there is no block?

thats what im trying to check that positon where its suppost to be

i think i got it to work using this
what you did ill do a bit more testing then ill give u solution

for i = 1, 4 do
			local position = HRP.Position + HRP.CFrame.LookVector * i * 6
			local rayResult = workspace:Raycast(position, -CFrame.identity.LookVector * 200)
				if rayResult then
				print("IS")
			else
				print("ISNT")
					break
				end
		end

Okay, I see, so couldn’t you cast a ray from above the block’s target position, in the downward direction?

workspace:Raycast(part goal position + part.Size.Y, -CFrame.identity.LookVector * gridSize)

Only thing here is that you’d need a shorter ray. If a block is, say, between your grid size * 2 (let’s say 10) and 200 studs, it’ll still intersect a part which is why if you cast a ray that’s one grid size above, and it’s only a grid size length, it can only intersect that one part directly below it

i dont know where the part is just the vector 3 of the hrp and where its suppost to be

Right, you’d just cast a ray above where the part’s supposed to be (in the position of a theoretical adjacent block), in the downward direction, but only have the ray’s length be a grid size step long.

But how would i do that???

So suppose goalPosition is the position where the block should be.

local adjacentBlockPosition = goalBlockPosition + Vector3.new(0, gridSize, 0)
--[[
     ⬜ <- this part's CFrame would be equivalent of adjacentBlockPosition. Even if there isn't a part here it's just to visualize where it *would* be
⬜⬜  ⬜⬜
]]
local isPartHere = workspace:Raycast(adjacentBlockPosition, -CFrame.identity.LookVector * gridSize)
--[[
      ╻ <- suppose this is our ray, since we're casting it downwards, it will check that there is no part to intersect, thus we can ascertain there is no part here.
⬜⬜ ╹ ⬜⬜

had there been a block here, the ray would've intersected it
      ╻ <- it intersected the block below it
⬜⬜⬜⬜⬜
]]

Because Roblox doesn’t consider interior faces of a basepart a valid intersector, it wouldn’t intersect the theoretical block above the goal position.

--[[
     ⬜
⬜⬜ ╹⬜⬜ <-- pretend the ray is in the centre of the part
]]

it just always says there is a block there

local adjacentBlockPosition = SnapHRP + Vector3.new(0, GridSnap, 0)
		local isPartHere = workspace:Raycast(adjacentBlockPosition, -CFrame.identity.LookVector * GridSnap)
		
if Ray then
	print("IS")
else
	print("Isnt")
end

You’re casting a ray from above the character, not the block’s goal position (unless you want the block to be in the position of the root part, in that case you’d have to add the character to be blacklisted via a RaycastParams)

the snaphrp is where the blocks is

local SnapHRPY = Snap(HRP.Position.Y - GridSnap)
--print(SnapHRPY)
local SnapHRP =  Vector3.new(SnapHRPX, SnapHRPY, SnapHRPZ)	

Isn’t HRP the humanoid root part’s position?
You’re also overwriting it here, this line will reset all axes back to 0:

removed the

local HRP = Vector3.new(HRP)

a while ago

yes hrp is humanoidrootpartposition the snaphrp is where the block should be

what is cframe.identity???

Right but you’re setting it to be in front of the root part just grid snapped :

A blank cframe