I would like to make a tree generator similar to the one used in lumber tycoon 2. However I have no idea where to start with CFrame. I’ve looked for tree generators on the developer forum and I don’t like the way the trees generate I want them to grow and not instantly appear. I have tried using Tween Service on the branch of one of the generators and it didn’t turn out well.
First, you should make a plan for how exactly you want the trees to grow. Write it out in great detail (in English or pseudo code).
Some hand-built examples of what you want the final tree to generally look like would also be helpful.
Once you do that, this forum can probably help you brainstorm implementation ideas much more effectively!
I want to have trees grow from random generation while slowly growing bigger over time. So the tree first grows out of the ground and then grows extra branches until its matured.
Do you want an animation between stages, or just a switch of models after x amount of time?
I would like the trees to not have stages and grow from the ground using CFrame or Tween Service but I have no idea where to start. I don’t want the trees to be pre-made I want a script to generate them. However I don’t know where to start or what documentation I would need to look at.
After A bit of work I’ve made this however I don’t know how to make the branches growing as the tree instantly generates.
local minh, maxh = 20, 70
local size = 14
local width = 3
function generate(position, angle, width, length, level)
local part = Instance.new('Part')
part.Anchored = true
part.Parent = script.Parent.Parent
part.Size = Vector3.new(width, length, width)
part.Position = position
part.Orientation = angle
part.BrickColor = BrickColor.new("Brown")
part.Material = Enum.Material.Concrete
if level >= 3 then
part.CanCollide = false
end
-- generate trunks from top
part.CFrame = (part.CFrame * CFrame.new(0,part.Size.Y/2,0))
local top = (part.CFrame * CFrame.new(0,part.Size.Y/2,0)).p
if (width > 0.5 and 4 - level > 0) then
for i=1, math.random(1,5 - level) do
generate(top, Vector3.new(math.random(minh, maxh), math.random(360), math.random(minh, maxh)), width * 0.8, length * 0.9, level + 1)
end
else
local leaf = Instance.new('Part')
leaf.Parent = script.Parent.Parent
leaf.Shape = Enum.PartType.Ball
leaf.Material = Enum.Material.Grass
leaf.Name = 'Leaf'
leaf.Size = Vector3.new(math.random(5,20), math.random(5,20), math.random(5,20))
leaf.Position = top
leaf.Anchored = true
leaf.Color = Color3.fromRGB(0, math.random(100, 150), 0)
leaf.CanCollide = false
end
end
generate(script.Parent.Position + Vector3.new(0, -1, 0), Vector3.new(0, 0, 0), width, size, 0)
We can randomly place a part with zero height, and tween it to increase its height and position so that it’s on the ground and growing, perhaps
local tweenService = game:GetService("TweenService")
local function animate(part, trunkEndHeight, tweenInfo1)
local tween = tweenService:Create(
part,
tweenInfo1,
{
Size = Vector3.new(part.Size.X, trunkEndHeight, part.Size.Z),
Position = Vector3.new(part.Position.X, part.Position.Y + trunkEndHeight/2, part.Position.Z)
}
)
tween.Completed:Connect(function()
--[[
animate branches here,
maybe add another ".Completed function" for each of those tweens for twigs
]]
end)
tween:Play()
end
This may be a good starting point.
I’ve kinda got the code you made implemented however it doesn’t look right the part tween in the center outward.
robloxapp-20221022-1535286.wmv (1.6 MB)
Set the position of the part where it connects with the branch/trunk before it, and then just copy the tween.
My current Code if it helps.
math.randomseed(tick())
function dot(c1,c2)
local m = CFrame.Angles(math.pi/2,0,0)
return (c1*m).lookVector:Dot((c2*m).lookVector)
end
local tweenService = game:GetService("TweenService")
function animate(part, trunkEndHeight, tweenInfo1, c)
local tween = tweenService:Create(
part,
tweenInfo1,
{
Size = Vector3.new(part.Size.X, trunkEndHeight, part.Size.Z),
Position = Vector3.new(part.Position.X, part.Position.Y + trunkEndHeight/2, part.Position.Z)
}
)
tween.Completed:Connect(function()
Branch(part,c-1)
end)
tween:Play()
end
local leaf_mult = {
Vector3.new(.8,.4,.8);
Vector3.new(.7,.55,.7);
Vector3.new(.85,.75,.85);
Vector3.new(.65,.55,.65);
Vector3.new(.75,.5,.9);
}
function Branch(base,c)
if c <= 0 then
local leaves = game.ServerStorage.Leaves:Clone()
local vol = base.Size.x+base.Size.y+base.Size.z
leaves.Size = leaf_mult[math.random(1,#leaf_mult)]*math.random(vol/3*12,vol/3*14)/2.5
leaves.CFrame = base.CFrame * CFrame.new(0,base.Size.y/2,0)
leaves.Parent = base.Parent
else
local pos = base.CFrame*CFrame.new(0,base.Size/2,0)
local height = base.Size.y
local width = base.Size.x
local nb = math.random(2,2)
local r = math.random(45,135)
local da = math.random(20+55/c,40+40/c)
local ba = math.random(-da/3,da/3)
for i=0,nb-1 do
local branch = base:Clone()
local h = height*math.random(95,115)/100
local new = branch.CFrame * CFrame.new(0,height/2,0) * CFrame.Angles(0,0,math.rad(ba))
new = new * CFrame.Angles(0,i*(math.pi*2/nb)+r,math.rad(da/2)) * CFrame.new(0,h/2,0)
local w = dot(new,branch.CFrame)*width*0.9
branch.Size = Vector3.new(w,0,w)
local timee = h/2
local info = TweenInfo.new(timee,Enum.EasingStyle.Linear,Enum.EasingDirection.Out)
animate(branch,h,info, c)
branch.CFrame = new
branch.Parent = base.Parent
end
end
end
function GenerateTree(location,complexity,width,height)
local tree = Instance.new("Model")
tree.Name = "Tree"
tree.archivable = false
tree.Parent = workspace
local base = game.ServerStorage.Trunk:Clone()
base.Parent = tree
base.Size = Vector3.new(width,height,width)
base.CFrame = CFrame.new(location) * CFrame.new(math.random(-10,10),height/2,math.random(-10,10)) * CFrame.Angles(0,math.rad(math.random(1,360)),0)
Branch(base,complexity)
return tree
end
local c,w,h=math.max(1,script.Parent.Complexity.Value),math.max(1,script.Parent.Width.Value),math.max(1,script.Parent.Height.Value)
GenerateTree(script.Parent.CFrame.p-Vector3.new(0,script.Parent.Size.Y,0),c,w,h)
What is the script’s fullname, like how do you identify it from game
Complexity is a numberValue of 3
Height is a numberValue of 9
and Width is a numberValue of 2
I got this, and it works for me.
math.randomseed(tick())
function dot(c1,c2)
local m = CFrame.Angles(math.pi/2,0,0)
return (c1*m).lookVector:Dot((c2*m).lookVector)
end
local tweenService = game:GetService("TweenService")
function animate(part, trunkEndHeight, tweenInfo1, c)
local tween = tweenService:Create(
part,
tweenInfo1,
{
Size = Vector3.new(part.Size.X, trunkEndHeight, part.Size.Z),
--Position = Vector3.new(part.Position.X, part.Position.Y + trunkEndHeight/2, part.Position.Z)
CFrame = part.CFrame + part.CFrame.UpVector * (trunkEndHeight/2) -- new
}
)
tween.Completed:Connect(function()
Branch(part,c-1)
end)
tween:Play()
end
local leaf_mult = {
Vector3.new(.8,.4,.8);
Vector3.new(.7,.55,.7);
Vector3.new(.85,.75,.85);
Vector3.new(.65,.55,.65);
Vector3.new(.75,.5,.9);
}
function Branch(base,c)
if c <= 0 then
local leaves = game.ServerStorage.Leaves:Clone()
local vol = base.Size.x+base.Size.y+base.Size.z
leaves.Size = leaf_mult[math.random(1,#leaf_mult)]*math.random(vol/3*12,vol/3*14)/2.5
leaves.CFrame = base.CFrame * CFrame.new(0,base.Size.y/2,0)
leaves.Parent = base.Parent
else
local pos = base.CFrame*CFrame.new(0,base.Size.Y/2,0)
local height = base.Size.Y
local width = base.Size.X
local nb = math.random(2,2)
local r = math.random(45,135)
local da = math.random(20+55/c,40+40/c)
local ba = math.random(-da/3,da/3)
for i=0,nb-1 do
local branch = base:Clone()
local h = height*math.random(95,115)/100
local new = branch.CFrame * CFrame.new(0,height/2,0) * CFrame.Angles(0,0,math.rad(ba))
new = new * CFrame.Angles(0,i*(math.pi*2/nb)+r,math.rad(da/2)) -- * CFrame.new(0,h/2,0)
local w = dot(new,branch.CFrame)*width*0.9
branch.Size = Vector3.new(w,0,w)
local timee = h/2
local info = TweenInfo.new(timee,Enum.EasingStyle.Linear,Enum.EasingDirection.Out)
branch.CFrame = new -- new
animate(branch,h,info, c)
-- branch.CFrame = new
branch.Parent = base.Parent
end
end
end
function GenerateTree(location,complexity,width,height)
local tree = Instance.new("Model")
tree.Name = "Tree"
tree.archivable = false
tree.Parent = workspace
local base = game.ServerStorage.Trunk:Clone()
base.Parent = tree
base.Size = Vector3.new(width,height,width)
base.CFrame = CFrame.new(location) * CFrame.new(math.random(-10,10),height/2,math.random(-10,10)) * CFrame.Angles(0,math.rad(math.random(1,360)),0)
Branch(base,complexity)
return tree
end
local c,w,h=math.max(1,script.Parent.Complexity.Value),math.max(1,script.Parent.Width.Value),math.max(1,script.Parent.Height.Value)
GenerateTree(script.Parent.CFrame.p-Vector3.new(0,script.Parent.Size.Y,0),c,w,h)
Is there a way to make it spawn multiple trees?
I think calling the function GenerateTree
multiple times works just fine.
Sorry if I don’t get your question if you have any more dm me because this is an already solved solution.