first post here so yeah
so i want to make trees rotate to terrain and mine are just either floating or inside the ground
i been looking for at least a hour
heres the code for the trees
any help is appreciated!
first post here so yeah
so i want to make trees rotate to terrain and mine are just either floating or inside the ground
Have you tried using the raycast normal?
These posts may help:
Your rayDirection should be straight down, not diagonal. If you could paste your code, that would help better than a picture.
Example rayDirection:
local rayDirection = Vector3.new(0, -100, 0)
You should also be using CFrame.lookAt like the posts showed, not CFrame.new.
You’re also missing the code that decides the Y position, could you just paste your whole code?
i tried to have it pointing down but it makes the trees rotate 90 degrees to the right and then it errors
local c = 24
local threshold = .94
local NoiseThreshold = 0.9
game.Workspace.Terrain:FillWedge(CFrame.new(x,y,z), Vector3.new(8,8,8), Enum.Material.Grass)
local TreeNoise = math.noise(x * frequency * c / resolution, z * frequency * c / resolution, seed) + 0.5
local TreeChance = math.random()
if TreeNoise > NoiseThreshold and TreeChance > threshold then
local Tree = game.ServerStorage.Objects.Tree:Clone()
local TreeHeight = Tree.PrimaryPart.Size.Y
local PartHeight = Part.Size.Y
local TreeY = y + 4.5 + TreeHeight
Tree:PivotTo(CFrame.new(x,TreeY,z))
Tree.Parent = workspace.Trees
local rayOrigin = Tree.PrimaryPart.Position
local rayDirection = Vector3.new(0, -50, 0)
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {Tree}
raycastParams.FilterType = Enum.RaycastFilterType.Exclude
raycastParams.IgnoreWater = true
local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)
print(raycastResult)
print(rayOrigin)
print(rayDirection)
-- print(raycastResult.Normal)
Tree:PivotTo(CFrame.lookAt(raycastResult.Position,raycastResult.Position + raycastResult.Normal,raycastResult.Position))
--CFrame.lookAt(raycastResult.Position, raycastResult.Position + raycastResult.Normal)
Tree.Parent = workspace.Trees
local randidk = math.random(1,7)
Tree.Leaves.UsePartColor = true
if randidk == 1 then
Tree.Leaves.Color = Color3.fromRGB(75, 151, 75)
elseif randidk == 2 then
Tree.Leaves.Color = Color3.fromRGB(136, 151, 60)
elseif randidk == 3 then
Tree.Leaves.Color = Color3.fromRGB(151, 101, 121)
elseif randidk == 5 then
Tree.Leaves.Color = Color3.fromRGB(173, 51, 51)
elseif randidk == 6 then
Tree.Leaves.Color = Color3.fromRGB(191, 145, 80)
elseif randidk == 7 then
Tree.Leaves.Color = Color3.fromRGB(148, 46, 85)
end
end
I have to play devil’s advocate here and ask: Do you really need the trees to rotate in accordance to the terrain’s normals?
In the real world, trees always grow upwards. On hills and mountains, the roots follow the ground while the trunk always faces up towards the sky.
Why do you want to make the trees rotate to the terrain?
(Disclaimer: Images are not mine and are purely for educational purpose)
I feel like this is the part of the code that is going wrong, can you add a debug print to the CFrame.lookAt and show the return to me?
Does it print these?
And also here
i beg you to use dictionaries please
I don’t need it, I just think it makes the game looked polished
sorry i’m messing with code i added some to make it a lil easier to understand
-- calculates tree spawning
local y = (y1*y2*power*power)+y3
local c = 24 -- c is some constant you use to customise how the noise feels
local threshold = .94 -- This defines how dense the trees are (how close together, lower = more dense) [between 0 and 1]
local NoiseThreshold = 0.9 -- This defines the size of the biome (lower = bigger) [between 0 and 1]
game.Workspace.Terrain:FillWedge(CFrame.new(x,y,z), Vector3.new(8,8,8), Enum.Material.Grass)
local TreeNoise = math.noise(x * frequency * c / resolution, z * frequency * c / resolution, seed) + 0.5
local TreeChance = math.random()
if TreeNoise > NoiseThreshold and TreeChance > threshold then
-- Spawns trees
local Tree = game.ServerStorage.Objects.Tree:Clone()
local TreeHeight = Tree.PrimaryPart.Size.Y
local PartHeight = Part.Size.Y
local TreeY = y + 4.5 + TreeHeight
Tree:PivotTo(CFrame.new(x,TreeY,z))
Tree.Parent = workspace.Trees
-- raycast
local rayOrigin = Tree.PrimaryPart.Position
local rayDirection = Vector3.new(-90, -90, 0)
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {Tree}
raycastParams.FilterType = Enum.RaycastFilterType.Exclude
raycastParams.IgnoreWater = true
local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)
-- prints out if the raycast is nil the others idk why i put there
print(raycastResult)
print(rayOrigin)
print(rayDirection)
-- print(raycastResult.Normal)
Tree:PivotTo(CFrame.new(raycastResult.Position,raycastResult.Position + raycastResult.Normal))
--CFrame.lookAt(raycastResult.Position, raycastResult.Position + raycastResult.Normal)
Tree.Parent = workspace.Trees
local randidk = math.random(1,7)
Tree.Leaves.UsePartColor = true
-- makes the trees have different colors
if randidk == 1 then
Tree.Leaves.Color = Color3.fromRGB(75, 151, 75)
elseif randidk == 2 then
Tree.Leaves.Color = Color3.fromRGB(136, 151, 60)
elseif randidk == 3 then
Tree.Leaves.Color = Color3.fromRGB(151, 101, 121)
elseif randidk == 5 then
Tree.Leaves.Color = Color3.fromRGB(173, 51, 51)
elseif randidk == 6 then
Tree.Leaves.Color = Color3.fromRGB(191, 145, 80)
elseif randidk == 7 then
Tree.Leaves.Color = Color3.fromRGB(148, 46, 85)
end
end
also heres the error
i thought you meant like things on what they do oops.
i also got other objects like rocks ,bushes ,ect
This is really late, but does this work?
Code:
-- calculates tree spawning
local y = (y1*y2*power*power)+y3
local c = 24 -- c is some constant you use to customise how the noise feels
local threshold = .94 -- This defines how dense the trees are (how close together, lower = more dense) [between 0 and 1]
local NoiseThreshold = 0.9 -- This defines the size of the biome (lower = bigger) [between 0 and 1]
game.Workspace.Terrain:FillWedge(CFrame.new(x,y,z), Vector3.new(8,8,8), Enum.Material.Grass)
local TreeNoise = math.noise(x * frequency * c / resolution, z * frequency * c / resolution, seed) + 0.5
local TreeChance = math.random()
if TreeNoise > NoiseThreshold and TreeChance > threshold then
-- Spawns trees
local Tree = game.ServerStorage.Objects.Tree:Clone()
local TreeHeight = Tree.PrimaryPart.Size.Y
local PartHeight = Part.Size.Y
local TreeY = y + 4.5 + TreeHeight
Tree:PivotTo(CFrame.new(x, TreeY, z))
Tree.Leaves.UsePartColor = true
Tree.Parent = workspace.Trees
local rayOrigin = Tree.PrimaryPart.Position
local rayDirection = Vector3.new(0, -90, 0)
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {Tree}
raycastParams.FilterType = Enum.RaycastFilterType.Exclude
raycastParams.IgnoreWater = true
local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)
if raycastResult then
Tree:PivotTo(CFrame.lookAt(raycastResult.Position,raycastResult.Position + raycastResult.Normal))
end
local randidk = math.random(7)
-- makes the trees have different colors
if randidk == 1 then
Tree.Leaves.Color = Color3.fromRGB(75, 151, 75)
elseif randidk == 2 then
Tree.Leaves.Color = Color3.fromRGB(136, 151, 60)
elseif randidk == 3 then
Tree.Leaves.Color = Color3.fromRGB(151, 101, 121)
elseif randidk == 5 then
Tree.Leaves.Color = Color3.fromRGB(173, 51, 51)
elseif randidk == 6 then
Tree.Leaves.Color = Color3.fromRGB(191, 145, 80)
elseif randidk == 7 then
Tree.Leaves.Color = Color3.fromRGB(148, 46, 85)
end
end
Firstly, do the raycast before parenting the tree to the workspace. Calculate the desired X,Z location, and raycast down from the sky. Then you don’t need to worry about adding the tree you’re trying to place to your exclude list. Probably, you want to test that the ray hit Instance is actually Terrain too, not an already-placed tree, or you’ll stack them up. Really, you need a system to prevent overlap, but that’s a different topic.
This isn’t correct. rayOrigin should be up high, a position with a Y value that you know is above the ground height at the targeted X,Z location.
Secondly, rayDirection needs to be a vector, not Euler Angles. You want something like Vector3.new(0,-1024,0) to raycast straight down. The exact length should be long enough to hit the ground from whatever rayOrigin height you use.
Lastly, if you just set the pivot of the tree, to the raycastResult.Position, then this is assuming the pivot point of the tree model is the point on the tree that you want at ground-level. If it’s a point halfway up the tree, the tree will end up sunk into the ground. Offset accordingly.
CFrame.lookAt() is problematic to use when you have a normal vector that is straight up (0,1,0), because the lookAt function is meant for looking horizontally, and allows specifying an UpVector, but you can’t specify a RightVector. If your normal is up (expect with flat ground), you’re at a singularity. The correct approach is to manually construct the full orientation from the normal and your desired (presumably randomized) tree y-axis rotation, using CFrame.fromMatrix().
Yeah, I told the OP about that a week ago, so I just thought they had already fixed it without looking at the code. Sorry about that.
This solution is fairly complicated though, and I’m not very good at CFrame manipulation. If you can send a code sample for OP then that would probably help them alot.