Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
1

Ray casting's position goes higher then it should go?

Asked by 5 years ago

So im trying to make a ore spawning system but sometimes the ores go in the ground so I am trying to use ray-casting to find out where the floor really is but it instead puts the ores on the ceiling.. I have tried position and CFrame and they both do not work.

Code:

local ray = Ray.new(dub.Default.Position+Vector3.new(0,10,0), dub.Default.Position-Vector3.new(0,40,0))

local part, position = workspace:FindPartOnRay(ray, game.Workspace.Ores, false, true)

print(position.Y)

local objPos2 = Vector3.new(dub.Default.CFrame.X, position.Y, dub.Default.CFrame.Z)

dub:SetPrimaryPartCFrame(CFrame.new(objPos2))

If you could help it would be greatly appreciated!

0
Hey! Not sure if this is necessarily the case, but based on what's happening, it looks like your origin just might be too high. Granted your ceiling is less than 10 studs above your "dub"'s default position, the ray is hitting the ceiling before it can reach the ground. saenae 318 — 5y
0
The thing is though that it spawns on the ground and the ceiling is higher then 10 studs above the ground. Also it spawns like right under the ceiling not on top of it. But thanks for the thought! c: outlook1234567890 115 — 5y

1 answer

Log in to vote
2
Answered by
Scarious 243 Moderation Voter
5 years ago
Edited 5 years ago

When creating a ray, it is important to note what the two parameters are.

As shown here, a ray requires a Vector3 origin and a Vector3 direction.

You have correctly input the Vector3 origin parameter, assuming you want it to be 10 studs above the Vector3 dub.Default.Position.

You have incorrectly input the Vector3 direction parameter, as it should be a unit vector multiplied by a set range, which would be a numerical value. All that this means is that rather than using a target location, you should be using a direction. There are a couple ways you can go about doing this:

1) Using set directions and multiplying them by a set range

This method is quite simple, the basic directions are as follows:

  • Up: Vector3.new(0,1,0)
  • Down: Vector3.new(0,-1,0)

While there are more directions than this, it is harder to visualize, and they would be on the world axis, causing issues with anything you might need them for, except advanced purposes.

2) Converting the target to a Vector3 direction by using an inputted origin, target, and range.

This method is also rather simple, first you take the target Vector3 position, subtract the origin Vector3 position, take the unit vector of the outcome, and then multiply it by a set range, outputting a Vector3 direction parameter.

Here's a code example of what I just said:

local function toDirection(origin,target,range)
    -- This function will convert an inputted origin, target, and range into a Vector3 direction parameter for usage in creating a ray
    -- @param Vector3 origin : start position of a ray
    -- @param Vector3 target : target position of a ray
    -- @param Number range : distance (in studs) that a ray will fire / how far a ray will go until it stops

    return (target-origin).unit*range
end 

This function will convert an inputted origin, target, and range into a Vector3 direction parameter, so that you can create your ray.


Back to the original question, you want to find out where the floor actually is, so you will likely want to use a simple unit vector going in the "down" (Vector3.new(0,-1,0)) direction, and a range of 100.

Here's a code example of what I just said:

-- This will fire a ray down and return the part it hits, and the position it hits the part at.
-- @param Vector3 origin : start position of a ray
-- @param Vector3 down : down unit vector (unit vectors always have a magnitude of 1)
-- @param Number range : distance (in studs) that a ray will fire / how far a ray will go until it stops
-- @param Vector3 direction : direction (in this case "down") which the ray will fire at
-- @param Table ignorelist : Whatever objects/models/folders (including their children) which should not interfere with the ray 
-- @param Instance hit : Part which the ray hits, will return nil if the ray does not hit a part.
-- @param Vector3 pos : Position which the ray hits the part at, should and part be hit

local origin = dub.Default.Position
local down = Vector3.new(0,-1,0)
local range = 100

local direction = down*range
local ignorelist = {}

local ray = Ray.new(dub.Default.Position,direction)
local hit,pos = workspace:FindPartOnRayWithIgnoreList(ray,ignorelist)

Now this is not all that you wanted to do, you also wanted to set a model's CFrame to have it's old Position, but to contain a new Y value. This would be done using what is listed above and then adding on to it in the way you did.

While this may not be effective at keeping the old rotation, it will certainly change it's position. If you are interested in keeping it's rotation, please let me know and I would be happy to help.

Here is a finished code example of what you are looking for:

-- This will fire a ray down and return the part it hits, and the position it hits the part at.
-- @param Vector3 origin : start position of a ray
-- @param Vector3 down : down unit vector (unit vectors always have a magnitude of 1)
-- @param Number range : distance (in studs) that a ray will fire / how far a ray will go until it stops
-- @param Vector3 direction : direction (in this case "down") which the ray will fire at
-- @param Table ignorelist : Whatever objects/models/folders (including their children) which should not interfere with the ray 
-- @param Instance hit : Part which the ray hits, will return nil if the ray does not hit a part.
-- @param Vector3 pos : Position which the ray hits the part at, should and part be hit
-- @param Vector3 newpos : Position which has the old model location, except with an updated Y cooriinate.

local origin = dub.Default.Position
local down = Vector3.new(0,-1,0)
local range = 100

local direction = down*range
local ignorelist = {}

local ray = Ray.new(dub.Default.Position,direction)
local hit,pos = workspace:FindPartOnRayWithIgnoreList(ray,ignorelist)

local newpos = Vector3.new(dub.Default.CFrame.X,pos.Y,dub.Default.CFrame.Z)

dub:SetPrimaryPartCFrame(CFrame.new(newpos))

If you have any issues, or something isn't quite right, please let me know. I do however wish to know more about the issue you were having, since this may perhaps not be all that you need to do to solve the total issue you were having.

If you found this helpful, please give me an upvote and accept my solution as it makes the time spent answering this question in-depth worth it, and inspires me to provide more in-depth solutions to others!

1
Thanks so much for the help! I like how you explained everything very well! c: outlook1234567890 115 — 5y
Ad

Answer this question