SetPrimaryPartCFrame not working properly?

Hey there! So, im at the forum again because i have been trying to debug this little thing and nothing works. So, i want the trees to go perfectly on top of terrain, so i raycast it since its the only way i found on google.

(I added 30 cuz i thought it might work with it but it doesn’t work with and without the +30)

local origin = Vector3.new(pos.X, pos.Y+30, pos.Z)
					local direction = Vector3.new(0, -100000, 0)
					local ray = Ray.new(origin, direction)

					-- search for the collision point with the terrain
					local whitelist = { game.Workspace.Terrain }
					local ignoreWater = true
					local _, intersection, surfaceNormal, surfaceMaterial = game.Workspace:FindPartOnRayWithWhitelist(ray, whitelist, ignoreWater)
					
					local cframe = CFrame.new(intersection)
						* CFrame.new(
							math.random() * math.random(-10, 10),
							0,
							math.random() * math.random(-10, 10)
						)
						* CFrame.Angles(0, 2 * math.pi * math.random(), 0)
					
					tree:SetPrimaryPartCFrame(cframe)

and ofcourse, it doesn’t work. doing CFrame.new(intersection) does not work but doing CFrame.new(pos) does)??

(doing pos makes it so its not on the surface and some trees are buried underground)

I print CFrame.new(pos) and CFrame.new(intersection) and this is the output
image
I don’t see a difference except the Y axis because Pos is based on the chunk position and Intersection is based on the Terrain position so its higher so the tree can be placed normally and not sink underground.

Theres prob more im not seeing here but yeah…

Anyone know the solution?

Thanks!!

1 Like

Make sure that your raycast is actually hitting the ground, I am saying this because you are getting -99984 for Y-axis which is a number close to the maximum raycast length that you defined in the direction Vector3 that has Y-axis of -100000. If the raycast isn’t hitting anything, it will go until it reaches said limit, therefore, you can make an assumption that the ray didn’t hit the terrain.

1 Like

tried this:

local object, intersection, surfaceNormal, surfaceMaterial = game.Workspace:FindPartOnRayWithWhitelist(ray, whitelist, ignoreWater)

if object then
	print("hit")
elseif intersection then
	print("pos")
end

and it printed “pos” but not “hit”

Do you possibly know why its not hitting the terrain?

I added 60 to the Y axis and visualized where “origin” was and this is what it looks like:
image

Did you try visualizing the ray itself? If not, try it.

1 Like

image
Raycast is just at the void.

Try setting the whitelist to an empty array {}.

It did not work, as usual :frowning:char

I just noticed, you are using :FindPartOnRayWithWhitelist, notice the keyword “Part”?
The raycast system is ignoring the terrain as it’s looking specifically for a part. Use the new raycast API.

Here is a sample to give you an idea on how to use it:

local raycast_config = RaycastParams.new()
raycast_config.BruteForceAllSlow = false
raycast_config.IgnoreWater = true

local raycast_result = workspace:Raycast(part.Position, Vector3.yAxis * -1000, raycast_config)
if raycast_result then
	tree:PivotTo(CFrame.new(raycast_result.Position))
end

https://developer.roblox.com/en-us/api-reference/function/WorldRoot/Raycast
https://developer.roblox.com/en-us/api-reference/datatype/RaycastResult
https://developer.roblox.com/en-us/api-reference/datatype/RaycastParams

1 Like

Unable to cast Ray to Vector3

local direction = Vector3.new(0, -33, 0)
					local ray = Ray.new(origin, direction)

					local raycast_config = RaycastParams.new()
					raycast_config.BruteForceAllSlow = false
					raycast_config.IgnoreWater = true

					local raycast_result = workspace:Raycast(testPart.Position, Vector3.yAxis * -1000, raycast_config)
					if raycast_result then
						local intersection = raycast_result.Position
						
						local distance = (origin - intersection).Magnitude
						local p = Instance.new("Part")
						p.Anchored = true
						p.CanCollide = false
						p.Size = Vector3.new(0.1, 0.1, distance)
						p.CFrame = CFrame.lookAt(origin, intersection)*CFrame.new(0, 0, -distance/2)
						p.Parent = workspace

						local cframe = CFrame.new(intersection)
							* CFrame.new(
								math.random() * math.random(-10, 10),
								0,
								math.random() * math.random(-10, 10)
							)
							* CFrame.Angles(0, 2 * math.pi * math.random(), 0)

						tree:SetPrimaryPartCFrame(cframe)
						tree.Parent = workspace:WaitForChild("__MAP"):WaitForChild("Trees")

						table.insert(instances, tree)
					end
				end

It worked i guess but its still underground…
image

You are attempting to put Ray object into parameter that accepts Vector3 value.

local raycastConfig = RaycastParams.new()
raycastConfig.BruteForceAllSlow = false
raycastConfig.IgnoreWater = true

local raycastResult = workspace:Raycast(Vector3.new(pos.X, pos.Y + 30, pos.Z), Vector3.yAxis * -100000, raycastConfig)
if raycastResult then
	local cframe = CFrame.new(raycastResult.Position) * CFrame.Angles(0, 2 * math.pi * math.random(), 0)
	tree:PivotTo(cframe)
end

Also, you should not modify the position that your model will be set to after raycasting as it might get pushed somewhere into the terrain, randomize your raycast origin position instead.

1 Like

Still underground, The leaves are kind of peeking out of the ground tho.

image

Use pivot editor and snap the pivot of the tree model to the bottom of the trunk.

https://developer.roblox.com/en-us/resources/studio/Pivot-Tools

2 Likes

Ton more better!
image
but yeah, as you can see, only the leaves are shown

Moved the PrimaryPart down a bit and it looks like this now:
image
some are like 50% of the branch are underground tho

Try lowering the pivot even more by disabling pivot snapping and adjust it until your trees are placed as desired. Just be aware that SetPrimaryPartCFrame is deprecated and pivots should be used instead (like the PivotTo method), you also get more control over the origin.

1 Like

image
Alright, i lowered it a bit more.

Worked, Thanks!

I have spent 3 hours on this thing, im very happy rn, thank you!!

1 Like