Tree Generator Module

Sooo, this is my first time posting a topic , and i wanted to show my new Module, the tree generator module, i made this one because i wanted to try something new, and i always liked the way trees in Lumber Tycoon 2 grow, so i decided to remake it for learning purposes, it was my first time using so much CFrame so it was pretty hard to deal with displacement, but with some help i got to make it work, it’s looking like this in the moment:

Sakuras

What about making them tinier?

Tinier Sakuras

Or maybe some Namek like trees with an exagerated amount of Brunches?

Blue Tree

Autumn Tree

Added some color variation, thanks to @koziahss for the tip

Autumn CV

Screenshot_4

Random Tree

Screenshot_5

Some Graphics

I’ll be uploading more examples as i update the module :smiley:
Well, really liked the way it turned out, this is my Module, if you guys know any way of improving it, please tell me, i’ll comment everything as soon as possible:

--- TreeModule Create by @Chest_games, if your interested in my work and want to contact me, just hit me on my discord Pedraunzin#0411, i'll answer any question asap. Thank you for using my Module!!

local TreeModule = {}

--- Contructors for better performance
local CFramenew = CFrame.new
local CFrameAngles = CFrame.Angles
local Vector3new = Vector3.new
local rand = math.random
--- This method takes action upon growing the tree parts and updating it's postitions
TreeModule.GrowthMethod = function(part, leafpart, increase, cframe, timer, finalsize, weld, tobeweld)
	repeat
		
		leafpart.CFrame = cframe * CFramenew(0,part.Size.y,0)
		
		--- This is a chance to the growing part to grow in between the timer chosed
		local randchance = rand(0,100)
		
		if randchance < 50 then
			if weld then
				weld.Part0 = nil
				weld.Part1 = nil
				part.Size = Vector3new(part.Size.x, part.Size.y+increase, part.Size.z)
				part.CFrame = cframe * CFramenew(0,part.Size.y/2-0.4,0)
				leafpart.CFrame = cframe * CFramenew(0,part.Size.y,0)
				weld.Part0 = part
				weld.Part1 = tobeweld
				
			else
				part.Size = Vector3new(part.Size.x, part.Size.y+increase, part.Size.z)
				part.CFrame = cframe * CFramenew(0,part.Size.y/2-0.4,0)
				leafpart.CFrame = cframe * CFramenew(0,part.Size.y,0)
				
			end
		end
		wait(timer)
		
	until part.Size.y >= finalsize
end

--- Coloring stuff, just leave it there :DD
TreeModule.Color3Gather = function(colorstring)
	local color = BrickColor.new(colorstring).Color
	local hue, saturation, value = color:ToHSV()
	local random = rand(-10,10)/100 + saturation
	if random > 1 then
		random = 1
	end
	local newcolor = Color3.fromHSV(hue, random, value)
	return newcolor
end

--- This method creates new branches from the last grown branch or root
TreeModule.BranchGenerator = function(root, leaf, nexttime, branches, leafcolor, woodencolor)

	local ySizeB = root.Size.y
	local yRotationB = rand(0,20)
	local xRotationB
	local zRotationB
	
	local newBranchChance = rand(0,100)
	
	for i = 1, branches do

		if i == 1 then
			xRotationB = rand(10,20)
			zRotationB = rand(10,30)

		elseif i == 2 then
			xRotationB = (xRotationB + rand(0,10))*-1 
			zRotationB = (zRotationB + rand(0,10))*-1

		elseif i == 3 then
			xRotationB = rand(20,30)
			zRotationB = rand(20,30)*-1
		else
			xRotationB = xRotationB*-1
			zRotationB = zRotationB*-1
		end

		local Branch = Instance.new("Part")
		Branch.Name = "Branch"
		local weld = Instance.new("WeldConstraint")
		
		local Leaf = Instance.new("Part")

		Leaf.Name = "Leaf"
		Leaf.Anchored = true
		Leaf.Size = Vector3.new(leaf.Size.x+0.5,leaf.Size.y,leaf.Size.z+0.5)

		Branch.Size = Vector3.new(root.Size.x-.2, 1, root.Size.z-.2)

		local newCFrameB = root.CFrame * CFramenew(0,(root.Size.y/2)-.2,0) * CFrameAngles(math.rad(xRotationB), math.rad(yRotationB), math.rad(zRotationB)) * CFramenew(0,Branch.Size.y/2,0)
		Branch.CFrame = newCFrameB
		Leaf.CFrame = newCFrameB * CFramenew(0,Branch.Size.y/2,0)
		weld.Part0 = Branch
		weld.Part1 = root
		Leaf.Material = Enum.Material.Grass
		Leaf.Color = TreeModule.Color3Gather(leafcolor)
		Leaf.CanCollide = false
		Branch.Material = Enum.Material.Concrete
		Branch.BrickColor = BrickColor.new(woodencolor)
		
		Branch.Parent = root
		Leaf.Parent = root
		weld.Parent = Branch
		
		--- Here you can change all the non-moduled properties like how many branches will a tree grow after the first 4, look at the parameters of the called function to change it properly
		spawn(function() 
			TreeModule.GrowthMethod(Branch, Leaf, 0.5, newCFrameB, 0.01, ySizeB, weld, root)
			if nexttime > 1 then
				TreeModule.BranchGenerator(Branch, Leaf, nexttime-1, rand(3,4), leafcolor, woodencolor)
				Leaf:Destroy()
			end
			
		end)

	end
end

--- Call this function to create a tree in the position of the rootpart, it should be inside a table. But if you don't like this way, the code is easily changable.
TreeModule.TreeGrowth = function(root, size, height, branches, woodencolor, leafcolor)
	for i, v in pairs(root) do
		
		local rp = v.Position
		
		local ySize = height
		local yRotation = rand(-45,45)
		local xRotation = rand(0,8)
		local zRotation = rand(-8,0)
		
		local WoodenRoot = Instance.new("Part")
		local Leaf = Instance.new("Part")
		
		Leaf.Name = "Leaf"
		Leaf.Anchored = true
		WoodenRoot.Name = "WoodenRoot"
		WoodenRoot.Anchored = true
		WoodenRoot.Size = Vector3new(size, size, size)
		Leaf.Size = Vector3new(WoodenRoot.Size.x*5, size, WoodenRoot.Size.z*5)
		local newCframe = CFramenew(rp.x, (WoodenRoot.Size.y/2)-0.7, rp.z) * CFrameAngles(math.rad(xRotation),math.rad(yRotation),math.rad(zRotation))
		WoodenRoot.CFrame = newCframe
		Leaf.CFrame = newCframe * CFramenew(0,WoodenRoot.Size.y/2, 0) 
		Leaf.Material = Enum.Material.Grass
		Leaf.Color = TreeModule.Color3Gather(leafcolor)
		Leaf.CanCollide = false
		WoodenRoot.Material = Enum.Material.Concrete
		WoodenRoot.BrickColor = BrickColor.new(woodencolor)
		
		WoodenRoot.Parent = v
		Leaf.Parent = WoodenRoot
		
		--- Here you can change all the no-moduled properties like how many brunches will a tree grow after the first 4, look at the parameters of the called function to change it properly
		spawn(function() 
			
			TreeModule.GrowthMethod(WoodenRoot, Leaf, 0.5, newCframe, 0.01, ySize)
			TreeModule.BranchGenerator(WoodenRoot, Leaf, branches, 4, leafcolor, woodencolor)
			Leaf:Destroy()
		end)
	end
end

return TreeModule
20 Likes

I think you have done s great job with that. :+1:t4:

A couple of miniscule optimizations though:

There is a new Random object that is basically the “better” way of getting random numbers. I don’t know if or why it is true but maybe you might want to consider using it for future code.

When instancing a objects it is recommended to not use the second parameter of Instance.new due to its slowness. It actually more performant to parents to the workspace at the very end. If you were to use this as a method for trees in-game you might hit lag spikes if there is a lot of instancing too.

Finally, might just be me but usually I like to store all the Constructors in a variable. I don’t remember where I heard this but doing it is faster than indexing.

local CFramenew = CFrame.new
for I = 1, 1000 do
    local MyCF = CFramenew()
end
-- Is faster than
for I = 1, 1000 do
    local MyCF = CFrame.new()
end

I think in term of visuals you might want to add a little colour variation to the leaves. Some lighter some darker.

But I think your work is pretty good. well done.

2 Likes

Thank you for replying, i didn’t know about the parenting stuff, thank you for that too, i’ll look at the code and see if i can optimize it a little, i thought of the lag when instancing objects, but i believe that it will not be a problem, cuz the original purpose of the module is to grow trees slowly, i’ll change the speed in the module asap, i’ll also update my script to work with the constructors thing, if it’ll run smoother, because my stress tests made my game go way slower than i imagined.

1 Like

This looks amazing good job. And my question is, is it growing on real time or in roblox time. If it’s growing on real time then this is amazing job.

1 Like

I made it to grow in roblox time, but i think i can try to do something with this idea, thank you for the feedback!

Sorry I forgot there is one more thing too. There is a new and improved library that you might want to look at

task.defer instead of spawn

Yeah sorry I forgot to link a resource on the parenting parameter for Instance.new
Here it is:

Happy coding :smiley:

1 Like

Thanks about the links, it’ll help a lot in future code, i tried using the task.defer, but it seems like it schedule it to happen a little after the code is called, and i need it to run just in the right moment so it didn’t work that well, but still thanks for your time! :smiley:

Hey, so sorry for bumping but could I get an example of how to use it? I can’t figure it out! :frowning_with_open_mouth:

1 Like

treeModule.TreeGrowth({tree},4,10,2,“Pine Cone”,“Sea Green”)

this is what i did u can tween it if u want