How to create a Ray with a multi-axis direction vector

Essentially I want to fire a ray from an arbitrary origin in both the Z and Y coordinates, so in this case the direction vector would Vector3.new(0, 1, 1). However, anytime I create a direction vector using more than one parameter, it completely breaks and just points towards a position in the world space instead.

Even adding multiple vectors together doesn’t work, for instance let’s say the direction vector is relative to a Part:

  • (Part.CFrame.UpVector * 1 + Part.CFrame.LookVector * 1) would break the Raycast in the same way as mentioned before.
Clarification (With drawings)

Excuse the poor drawings, but Vector3.new(0, 1, 1) is a ray inbetween the two vectors: Vector3.new(0, 1, 0) and Vector3.new(0, 0, 1).

To sum it up, I basically just want a direction vector as indicated in the third diagram.

1 Like

Adding the vectors together gives you a vector in-between them.

So Vector3.New(0, 1, 0) + Vector3.New(0, 0, -1) gives a vector pointing UP and Forward

One way I use sometimes to easily get a direction vector is create a CFrame using the lookAt() constructor and 2 positions. OriginPos and TargetPos, then use the .LookVector of that CFrame as my direction vector.

I use these literally all the time with raycasting.

1 Like

Sounds like it could work, do you mind providing me an example with all the necessary steps by any chance? I feel like I’ve tried everything but nothing is working for me.

local cf = part.CFrame
local dir = cf.LookVector + cf.UpVector --Forward + Up
local castResult = workspace:Raycast(cf.Position, (dir*castDist), CastParams)
1 Like

What would castDist be? Is it just an integer? If it is, couldn’t I just specify
local dir = cf.LookVector * (int) + cf.UpVector * (int) in the line where you initialize dir instead?

castDist is an integer but it serves as the magnitude of the direction. How far to go in that direction.

Technically yes you could do that but the integers would have to be exactly the same or you’d be changing the direction. So why write it twice?

Just tried this in studio with a part and it seemed to work, however I can’t get the same results when using just CFrames themselves.

The origin in this case isn’t based on the lookvector and upvector of a part, but instead of a position/CFrame in the world. Is there anyway I can get around this without using any parts?

The part just supplies the CFrame. So yea you could just use a CFrame.

The thing is that I’ve tried it, but it keeps pointing to a position in the WorldSpace instead.

local NewRaycastOrigin = CFrame.new(Raycast.Position.X, TrueHeight, Raycast.Position.Z)
local NewRaycastDirection = NewRaycastOrigin.UpVector * 5
local NewRaycast = workspace:Raycast(NewRaycastOrigin.Position, NewRaycastDirection, VaultRaycastParameters)

The RayCast.Position in this case is the intersection point of where the previous Raycast hit a wall.

An example of the issue I’m having, I added a LookVector Vector3 to it as well so it’s easier to see in the gif.
https://gyazo.com/047e03d09a682d22f9252ee685271b2e

That casts a ray starting at the position you provided to the CFrame directly upward 5 studs.

Yep, that was just an example of what I had so far. In the gif I added a LookVector to it so it’s easier to see. I essentially want it to go towards the direction the player is facing.

local cf = myChar.HumanoidRootPart.CFrame
local dir = cf.LookVector * 5

The problem is I can’t use the HumanoidRootPart for this due to the nature of what I’m trying to do, It must use the specific position I provided earlier otherwise this whole method is nil.

If you want to take a closer look, I’ll link the main thread that has the specifics of what I’m trying to do.

So if you need the raycast position to be higher then add an offset.

local cf = myChar.HumanoidRootPart.CFrame * CFrame.new(0,10,0) --Humanoid Position + 10 studs higher.

Wouldn’t work, as I said before it can’t rely on the HumanoidRootPart in this case.
The origin is at the edge of a part. Take a look at the thread I linked in the previous post, it has all the details.

Yeah I’ve been seen that post. Thats a complex problem. Your trying to calculate the distance between the two object to see if there is room to jump up there / in-between them. Which you could do with 2 raycasts if the parts are all rotated in specific ways. But what if they aren’t? Then the problem becomes alot more complex.

Do you really even need to check if its a player doing the vaulting? I could see the need for an NPC which your trying to write an AI for. But not for a player. Just let them vault and fail.

1 Like

I’m confused, the direction being described in WorldSpace is the expected behavior of raycasts? Raycasts in Roblox are really just segments which are two points in coordinate space. The direction is just an offset to the origin, which is offsetted in WorldSpace because it’s based on the coordinate world system.

I don’t see how you’re having issues manipulating the direction vector. Maybe something like this?

local cf = part.CFrame
local origin = cf + cf.LookVector * part.Size.Z * .5
local dir = (cf.LookVector + cf.UpVector) * 5
local ray = workspace:Raycast(origin.Position, dir.Position, raycastParams)


Test it yourself:
Baseplate.rbxl (35.6 KB)

Well… now that I think about it… you might be able to do it with 3 raycasts…

Cast forward from player to detect the obstacle, then into the object slightly from the hit position (this is now origin 2 and from inside the object it will automatically not detect it) Cast straight upward to hit anything above it… That hit pos is now org 3. Cast back down to get the first object top surface and then the dist from org3 to final hit pos is the distance between them. If that dist is large enough then you can fit through it.

That’s assuming its not some crazy shape. If we are talking blocks then it would work. But if there is a slanted surface or other jagged stuff in between then you’ll run into problems where the at certain times there is enough space and other points there isn’t. Then you have to do some kind of region3 block or part based Zone to verify it clear all the way width and all way through the gap.

I’ve been writing my own pathFinding AI for my NPCs and this particular problem I have not addressed yet, but I use similar techniques to allow them to jump across gaps and on top of platforms and find their way through different sorts of mazes.

That’s exactly my issue, the direction is supposed to just offset the Origin vector in a certain direction, however that’s exactly how it’s NOT behaving in my case. Instead of moving towards a position relative to the object (Let’s say Vector3.new(0, 5, 0), so 5 studs up relative to the object.) It’ll instead POINT towards the World position (0, 5, 0).

At least this is what I suspect.

I do need to check where the player is vaulting most of the time since it could give them the ability to scale up walls they aren’t supposed to.