For a long time now, the Lumber Tycoon 2 tree generation system has been fascinating me, and I’ve been trying to recreate my own system but I kept failing until now!
The script probably has a ton of bugs and is obviously not the best. I struggle to use CFrame, so it’s pretty hard for me to fix them, but I thought that it would be cool to share this resource since there isn’t much about open source tree generation system out there.
--// Module script, scripted by hypixel26
local TreeGenerationPackage = {}
function GenPart(Name, Size, Type)
local Part = Instance.new("Part")
local Attachment
Part.Size = Size
Part.Anchored = true
Part.Name = Name
if Type == "Wood" then
Part.Color = Color3.fromRGB(119, 81, 55)
Part.Material = Enum.Material.Concrete
Attachment = Instance.new("Attachment")
Attachment.Parent = Part
Attachment.Position = Vector3.new(0, Part.Size.Y / 2, 0)
elseif Type == "Leaf" then
Part.Color = Color3.fromRGB(115, 209, 120)
Part.Material = Enum.Material.Grass
Part.Transparency = .05
Part.CanCollide = true
end
return Part, Attachment
end
function PlaceOnAttachment(Attachment, CenterAttachment, Part, AngleXZ)
Attachment.WorldPosition = CenterAttachment.WorldPosition
Attachment.WorldOrientation = Vector3.new(math.random(AngleXZ - 20, AngleXZ + 20) + (math.random() * -1), math.random(0, 180), -math.random(AngleXZ - 20, AngleXZ + 20) + (math.random() * -1))
Part.CFrame = Attachment.WorldCFrame * CFrame.new(0, Part.Size.Y / 2 - .25, 0)
Attachment.Position = Vector3.new(0, Part.Size.Y / 2, 0)
end
function TreeGenerationPackage.GenerateTree(Origin, Name)
if Origin == nil and Name == nil then return end
local OriginHit = workspace:Raycast(Origin + Vector3.new(0, 10, 0), Vector3.new(0, -1000, 0))
Origin = (OriginHit ~= nil) and OriginHit.Position or Origin
local TreeElements = {}
local SubBranchesList = {}
local X, Y, Z = math.rad(math.random(0, 15)), math.rad(math.random(0, 180)), math.rad(math.random(0, 15))
local Branches = 3
local IndexAngle = math.floor(45 / Branches)
local Trunk, Center = GenPart("Trunk", Vector3.new(1, 8, 1), "Wood")
table.insert(TreeElements, Trunk)
Trunk.CFrame = CFrame.new(Origin + Vector3.new(0, Trunk.Size.Y/2 - .6, 0)) * CFrame.Angles(X, Y, Z)
for Integer = 1, Branches do
local Branch, Attachment = GenPart("Branch", Vector3.new(.55, 7.5, .55), "Wood")
table.insert(TreeElements, Branch)
PlaceOnAttachment(Attachment, Center, Branch, IndexAngle * Integer)
local SubBranches = math.random(2, 3)
local IndexAngle2 = math.floor(45 / SubBranches)
for _Integer = 1, SubBranches do
local SubBranch, SubAttachment = GenPart("SubBranch", Vector3.new(.35, 4.5, .35), "Wood")
table.insert(TreeElements, SubBranch)
table.insert(SubBranchesList, SubBranch)
PlaceOnAttachment(SubAttachment, Attachment, SubBranch, IndexAngle2 * _Integer)
end
Attachment:Destroy()
end
for _Index, Value in ipairs(SubBranchesList) do
if Value:IsA("BasePart") then
local Leaves = math.random(1, 2)
local IndexLeafAngle = math.floor(15 / Leaves)
for Integer = 1, Leaves do
local Leaf = GenPart("Leaf", Vector3.new(4.5, .85, 4.5), "Leaf")
table.insert(TreeElements, Leaf)
Leaf.CFrame = CFrame.new(Value.Attachment.WorldPosition.X, Value.Attachment.WorldPosition.Y + Leaf.Size.Y / 2 - .5, Value.Attachment.WorldPosition.Z) * CFrame.Angles(math.rad(IndexLeafAngle * Integer), math.random(0, math.pi), math.rad(IndexLeafAngle * Integer))
end
Value.Attachment:Destroy()
end
end
Center:Destroy()
local TreeModel = Instance.new("Model")
TreeModel.Name = Name
for _Index, Value in ipairs(TreeElements) do
if Value:IsA("BasePart") then
Value.Parent = TreeModel
end
end
TreeModel.Parent = workspace
return TreeElements, TreeModel
end
return TreeGenerationPackage
Usage :
--// Server script
local TreeGen = require(game:GetService("ReplicatedStorage"):WaitForChild("Shared").GenerationScript)
TreeGen.GenerateTree(Vector3.new(0, 0, 0), "My first tree")