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!
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:
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!