ah ok thanks I will try using rays

It would have the prerequisite of the front side being the one with the branches’ point, although you could circumvent that buy using rightvector or upvector.

Also how would I use ray.Magnitude? Isn’t magnitude a measurement for distance?

yes, i think there was a way to establish a ray’s lenght, and if it touched nothing it would return where the ray would end based on lenght provided. so then you use (origin - hitPosition).Magnitude to get the effective distance between the start and end.

Firstly, why rays? You can just use CFrames.

Im not very good with CFrames how would I do what you suggested?

If you get the relative CFrame of a branch then you can multiply it with half the Y axis size which will get you the tip of the branch then you can create another branch there. Also, you can use CFrame.Angles if you want to rotate the new branch.

alright, thank you for the explanation

Rays are used to check collisions. idk why you need it in this case

you just need to generate a random direction in a 3d cone relative to the previous generated direction.

```
local rng_v = Random.new()
function RandomVectorOffset(v, maxAngle) --returns uniformly-distributed random unit vector no more than maxAngle radians away from v
return (CFrame.new(Vector3.new(), v)*CFrame.Angles(0, 0, rng_v:NextNumber(0, 2*math.pi))*CFrame.Angles(math.acos(rng_v:NextNumber(math.cos(maxAngle), 1)), 0, 0)).LookVector
end
```

The function by

you’ll start by getting the first direction from the up vector of the base

```
local max_angle = math.pi/8
local FirstDirection = RandomVectorOffset(BasePart.CFrame.UpVector, angle)
```

and then

```
local SecondDirection = RandomVectorOffset(FirstDirection, angle)
```

and keep going like that in a loop getting random directions that are limited by the angle you setted up and building the tree trunk

would this allow for a branch off of another branch or just building branches on a trunk

yes for sure

if you want 2 branchs

make 2 directions out of the previous direction instead of 1 direction

I actually just learnt this by researching your problem in a more mathematical way

I’m having troubles understanding, these are just angles right?

It’s not easy btw. basically I gave you just the key to the problem you’re facing

which is generating a random direction in a 3D cone.

I might implement it in my free time

I’ll make sure to share it with you and the community if it is successful

ah alright I’m just very confused as to how you build off of the angles

You can use the angles with CFrame.Angles. But remember it’s in radians.

I faced the same problem when I was younger. but I didn’t had enough math and cframe background to do it.

Now you reminded me of the problem I had. I guess right now I figured out the solution theoretically lol

Here I achieved one branching

this is the code that I used:

```
local PartTemplate = Instance.new("Part")
PartTemplate.Anchored = true
local function Line(a, b, parent)
local new = PartTemplate:Clone()
new.Size = Vector3.new(1,1, (a-b).magnitude)
new.CFrame = CFrame.new((a+b)/2, b)
new.Parent = parent
return b, new.CFrame.LookVector
end
local vec = Vector3.new
local v = {
ZERO = vec(0,0,0),
UP = vec(0,1,0)
}
local branchHeight = 5
local maxAngle = math.pi/4
local last, lastVec = Line(v.ZERO, v.UP*branchHeight, workspace)
local PartPerBranch = 10
local rng_v = Random.new()
function RandomVectorOffset(v, maxAngle) --returns uniformly-distributed random unit vector no more than maxAngle radians away from v
return (CFrame.new(Vector3.new(), v)*CFrame.Angles(0, 0, rng_v:NextNumber(0, 2*math.pi))*CFrame.Angles(math.acos(rng_v:NextNumber(math.cos(maxAngle), 1)), 0, 0)).LookVector
end
for i=0, PartPerBranch, 1 do
last, lastVec = Line(last, last+RandomVectorOffset(lastVec, maxAngle)*branchHeight, workspace)
end
```

hm, how would you split the branches though?

That’s what am going to try now

```
local PartTemplate = Instance.new("Part")
PartTemplate.Anchored = true
local function Line(a, b, parent)
local new = PartTemplate:Clone()
new.Size = Vector3.new(1,1, (a-b).magnitude)
new.CFrame = CFrame.new((a+b)/2, b)
new.Parent = parent
return b, new.CFrame.LookVector
end
local vec = Vector3.new
local v = {
ZERO = vec(0,0,0),
UP = vec(0,1,0)
}
local branchHeight = 5
local maxAngle = math.pi/8
local last, lastVec = Line(v.ZERO, v.UP*branchHeight, workspace)
local PartPerBranch = 1000
local rng_v = Random.new()
function RandomVectorOffset(v, maxAngle) --returns uniformly-distributed random unit vector no more than maxAngle radians away from v
return (CFrame.new(Vector3.new(), v)*CFrame.Angles(0, 0, rng_v:NextNumber(0, 2*math.pi))*CFrame.Angles(math.acos(rng_v:NextNumber(math.cos(maxAngle), 1)), 0, 0)).LookVector
end
for i=0, PartPerBranch, 1 do
last, lastVec = Line(last, last+RandomVectorOffset(lastVec, maxAngle)*branchHeight, workspace)
local branch = math.random(0,1) == 0
if branch then
local last, lastVec = Line(last, last+RandomVectorOffset(lastVec, math.pi/2)*branchHeight, workspace)
for i=0, 3, 1 do
last, lastVec = Line(last, last+RandomVectorOffset(lastVec, maxAngle)*branchHeight, workspace)
end
end
end
```

I found the pattern. now I just need to generalize it into a function

This is the most beautiful thing I have ever made through a devforum question xD