Woody plants in Grow a Garden: a developer guide to in-game trees and shrubs
A new wave of relaxing farming and gardening sims has put vegetation back at the center of gameplay, and that shift puts woody plants in a strange spot. They look decorative, but in a modern gardening sim they have to grow, react to seasons, cast shadows, and survive being chopped down by a player with an axe. For a developer or technical artist working on a title in the same family as Grow a Garden, the design and engineering decisions around trees, bushes, and shrubs shape both the look of the world and the budget of every scene.
This guide walks through the production questions a small team should answer before any artist starts sculpting bark. It covers what counts as a woody plant, how a game’s growth and persistence system should treat them, which asset and shading techniques hold up at scale, and where performance usually breaks first. The goal is to give a single developer, technical artist, or producer enough structure to make defensible decisions without locking the team into a single engine or workflow.
What counts as a woody plant in a gardening game
Outside of games, a woody plant is any plant that produces wood as its structural tissue and persists above ground across dormant seasons, including trees, shrubs, lianas, and some bamboos. Inside a farming sim, that biological definition matters less than the gameplay behavior. A species is “woody” when it has persistent stems that the player can see change across days or seasons, when it can support a fruit or flower cycle, and when it is too large to harvest with a single click on a seed icon.
From a design point of view, this definition shapes four systems at once: the catalog, the growth simulator, the rendering pipeline, and the player’s mental model. A clear answer to “is this thing woody or herbaceous” lets the team decide whether the item lives in a tree nursery tab, whether it draws from a branch LOD group, whether it gets a season tint, and whether the player expects an axe, shears, or a scythe to remove it.
Most shipped gardening sims settle on a working list that includes fruit trees, ornamental trees, berry bushes, flowering shrubs, hedges, and climbing vines on trellises. Bulbs, root vegetables, and small annual flowers stay in the herbaceous bucket even when the player might loosely call them “plants.” The sharper the team is about this split, the cleaner the catalog, the more predictable the save file, and the easier the UI design becomes.
Why trees and shrubs break a simple crop system
Most farming games already have a system for crops: a tile, a seed, a timer, a harvest. Woody plants do not fit that loop well, and the failure usually shows up as one of three symptoms during playtest.
- Woody plants feel like a reskinned crop. Players tap the tree, get a fruit, the fruit respawns on a timer, and the experience is identical to a pumpkin. The team has wasted a chance to make the world feel layered.
- Woody plants are invisible to progression. A tree that never matures, never blocks a path, never shades a crop, and never changes color is just a static prop. Players notice and stop caring about it by hour five.
- Woody plants tank performance. A forest of detailed trees, each with their own wind animation and shadow map, can eat a mid-range laptop’s frame budget in one valley. The team either strips the world or strips the variety.
The fix is to design the woody plant system as a separate set of objects with their own growth states, their own interaction verbs, and their own rendering budget. Treating trees as “crops with a longer timer” tends to produce the flat, prop-like result players complain about in reviews.
Core systems that have to agree on what a woody plant is
Before any model is built, four systems in the engine have to agree on the same definition. If they disagree, you get the classic bug where the save file says a tree is mature, the renderer still draws a sapling, and the growth system thinks the tree is a seedling again.
Catalog and data layer
The catalog entry for a woody plant needs more fields than a normal crop. A practical minimum data set looks like the table below.
| Field | Why it matters | Example value |
|---|---|---|
| Species ID | Stable identifier for save files and analytics | apple_fuji |
| Growth stages | Number of visual and behavioral transitions | 4 (seedling, sapling, juvenile, mature) |
| Stage durations | Real-time or in-game day cost per stage | 1, 3, 5, 8 in-game days |
| Persistent state | Whether the plant survives between sessions | true (vs. seasonal herbaceous) |
| Harvest verb | Tool or interaction that yields an item | scythe, axe, hand-pick |
| Pruning rules | Whether shape affects yield or regrowth | true for hedges, false for orchard trees |
| Root radius | Tile footprint for soil and irrigation | 2×2, 3×3, or radius 1.5 |
Once the catalog has these fields, every downstream system can read the same source of truth. If the team uses ScriptableObjects, data tables, or JSON, the rule is the same: do not let the growth simulator hard-code species behavior that the catalog already describes.
Growth and time layer
Growth has to be deterministic from the player’s point of view. A tree that matured on day 20 in one session must still be mature on day 20 after a reload, a system sleep, or a long offline period. That means:
- Store the planted day and the species growth table, not the current stage. Re-derive the stage on load.
- Run the growth update on a fixed cadence, not every frame. Once per in-game hour is usually fine for trees.
- Separate the visual stage from the productive stage. A tree can look mature but not yet bear fruit, which lets the team tune pacing without re-exporting meshes.
For simulation-heavy modes, the team may want a slower time scale for woody plants. A 30-day apple tree feels reasonable in real time. A 30-day oak feels absurd. Letting the catalog carry a per-species time scale keeps that decision in data, not in code.
Interaction and tool layer
Woody plants usually need at least three interaction verbs: inspect, harvest, and remove. The interaction system should resolve them in a stable priority so a player cannot soft-lock a tree by spamming the wrong tool.
| Verb | Default tool | Output | Effect on plant | |
|---|---|---|---|---|
| Inspect | Hand cursor | Info panel with species, age, health | None | |
| Harvest | Scythe or hand | Fruit, flower, or branch item | Resets productive stage, plant stays | |
| Prune | Shears | Pruned material or shape change | Modifies a shape or yield modifier | |
| Remove | Axe or shovel | Wood, sapling, or stump object | Plant destroyed, tile freed |
| Plant class | Tri budget (LOD0) | LOD steps | Texture set | Notes |
|---|---|---|---|---|
| Hero fruit tree | 6,000-10,000 | 3 | 2K albedo, normal, roughness | Player interacts, can inspect |
| Ornamental shrub | 1,500-3,000 | 2 | 1K atlas, normal | Often used in clusters |
| Hedge segment | 800-1,200 | 1 | 1K tiled | Repeats along paths |
| Background tree | 300-600 | 1 or billboard | 512 atlas | Shares impostor sheet |
Most of the cost in a forest is not in the tree itself, it is in the leaves. A few rules of thumb keep leaf cost under control:
- Use opacity-mapped leaf cards for distant trees and small shrubs. Hand-placed geometry is wasted once the camera is more than a few meters away.
- Keep one wind shader and parameterize it by species. Each species can have its own amplitude, frequency, and trunk stiffness without writing a new shader.
- Avoid unique normal maps per species. Reuse a bark atlas and tint it by species. The player almost never inspects a tree’s bark up close.
For shrubs, a hybrid mesh with a hand-shaped silhouette plus a translucent leaf shell is usually enough. The silhouette carries the readable shape, the shell carries the volume, and neither has to be high poly.
Wind, seasons, and environmental reactivity
Woody plants earn their keep when the world reacts to them. Three reactions pay for themselves: wind, season tint, and growth over time. Each is cheap to implement once the data layer is right.
Wind does not need per-vertex noise. A simple trunk sway driven by a global wind vector, plus a leaf-card roll driven by the same vector, reads correctly at typical camera distances. The trick is to keep the trunk stiffness and the leaf amplitude in the catalog so the team can tune a willow versus an oak without writing a new shader.
Season tint is the cheapest way to make a forest feel alive. A single shader property that mixes between spring, summer, autumn, and winter palettes, driven by the in-game day of year, is enough. The catalog carries the per-species color anchors, so a maple goes red in autumn and a pine stays green. The art team gets more variety per asset, and the simulation team does not have to add a new state machine.
Growth over time is the highest-cost reaction, because it implies LOD swaps and possibly mesh swaps. A common mistake is to rebuild the mesh at each stage. A safer pattern is to author one mesh per stage, swap them on stage transitions, and let the LOD group recompute. The visual jump between stages is small enough that players read it as growth, not as a pop.
Pruning, shaping, and player agency
Once a player can own a hedge, they will expect to shape it. For additional context, Pruning is the system that turns woody plants from set dressing into a tool. A minimal pruning system needs:
- A shape data field on the plant, stored as a small grid or list of trim marks.
- A preview ghost while the player holds the shears, so the trim is committed only on confirm.
- A yield modifier that maps shape to fruit or flower count, so pruning has a real reason to exist.
- An undo path within the same play session. A wrong click should not cost a season of growth.
For a small team, the safest scope is “topiary hedges plus a single fruit tree with three shape presets.” A full L-system editor for player-shaped topiary is a separate project. Keeping the scope honest is what keeps pruning from blowing the production timeline.
Performance: where woody plants actually break a frame
Most performance regressions in a forest scene come from a small set of predictable causes. Naming them helps the team profile with intent rather than guesswork.
- Shadow map overdraw. Every tree casts a shadow on a 2048 map, and the GPU spends the frame budget sorting leaves. Drop shadow resolution for background trees, or move them to a static shadow cascade.
- Per-instance shader cost. Each unique material or branch graph in the scene forces a draw call. Sharing materials across species and using GPU instancing for hedges and background trees usually pays for itself.
- CPU animation cost. A wind shader that runs on every vertex of every leaf is cheap on the GPU but expensive in vertex throughput. Use a low-poly trunk and let the leaf cards carry the visual cost.
- Streaming and pop-in. Trees that load mid-frame cause hitches. Stream the woody plant catalog with the same priority as the terrain tiles, and use a fade-in for newly visible instances.
- Save file bloat. A few hundred trees, each with a custom shape, will balloon a JSON save. Quantize shape data and cap the field size in the catalog.
A useful rule of thumb is to budget the woody plant set as roughly 20-30 percent of the scene’s draw calls and 10-15 percent of the GPU frame time. If the share climbs above that without a reason, the team has either over-detailed the background set or under-LODed the hero set.
Save, persistence, and season resets
Woody plants are persistent by definition, so the save system has to carry their state across sessions. A few patterns make this much easier to maintain:
- Store species ID, planted day, and accumulated modifiers. Re-derive the visual stage on load.
- Keep pruning data in a compact form. A 4×4 trim grid fits in a small integer array per plant.
- Separate persistent state from transient state. A wind gust that bends a branch should not write to disk.
- Plan for a season reset if the game has one. A spring reset that destroys all herbaceous crops but leaves trees standing is a common, player-friendly choice.
It is also worth deciding early whether the game will support cross-save between platforms. If it does, every woody plant field has to survive a JSON round-trip, which usually rules out engine-specific types in the save schema.
Designing the catalog so the world stays interesting
Variety without chaos is the hard part of a woody plant set. A catalog that grows by accretion tends to produce three fruit trees that look the same and a long tail of species nobody uses. A few editorial rules help.
- Anchor the catalog in biomes, not in species. A “temperate orchard” biome with three trees, two shrubs, and one hedge is more usable than ten disconnected species.
- Cap the number of fruit-bearing species at first release. Four to six is plenty. The team can add more as a free content update.
- Make at least one species visually unique per biome, so a player can tell the orchard from the herb garden at a glance.
- Keep at least one evergreen species per biome, so winter does not strip the world of all structure.
For a small studio, the catalog question is also a scope question. A working approach is to start with one biome, ship it with the core growth and interaction loop, and treat additional biomes as a vertical content slice that reuses the same systems. A useful pattern is to keep the system generic and let the catalog carry the personality.
Accessibility, localization, and player reading
Woody plants interact with accessibility in three ways. They cast shadows, they have busy silhouettes, and they have tooltips. A few low-cost rules help most players.
- Offer a high-contrast foliage outline option. The default low-contrast leaves can wash out against a sunset sky for some color-vision profiles.
- Keep the tooltips short and consistent. The same field set per species is easier to localize than a free-text description.
- Use the same icon set for harvest, prune, and remove across all species. Players should not have to relearn a button for each tree.
- Tag the audio cues per verb, not per species. A player learns “axe sound” once, and every tree reuses it.
For a gardening sim with a long tail of casual players, accessibility is also a retention feature. A player who can keep playing despite a vision or motor preference is a player who stays for the second biome.
Common production pitfalls on small teams
The patterns below show up in postmortems of small gardening sims again and again. Naming them helps a new team avoid the same review-cycle pain.
- Letting art start before the catalog is locked. The result is ten species that need to be re-exported when the data layer changes.
- Treating pruning as a stretch goal. Pruning usually slips anyway, and re-scoping it late is more expensive than designing the data shape for it from day one.
- Mixing static and dynamic trees in the same LOD group. A static background tree should not share an LOD with a player-inspectable hero tree, because the budgets are different.
- Forgetting the “remove” verb. A player who cannot clean up a misplanted tree will quietly resent the game.
- Skipping the offline test. A growth system that works in a single session can fail after the player closes the laptop for a week.
Most of these pitfalls are not technical, they are sequencing. The technical fixes are usually well known. The hard part is to lock the data layer, the growth system, and the interaction verbs before the first art task opens.
A practical checklist before greenlighting woody plants
Before the team commits to a woody plant set, run through the checklist below. Each item is a question that has bitten at least one shipped game.
- Is the species list locked, and does each entry carry growth stages, stage durations, harvest verb, and pruning rules?
- Is the growth update fixed-cadence and deterministic on load?
- Do hero, mid, and background LOD groups have a tri budget per plant class?
- Does the wind shader use a global wind vector and per-species parameters, not per-vertex noise?
- Does the season tint come from a single shader property and per-species palette anchors?
- Does the pruning system have a preview ghost, an undo path, and a yield modifier?
- Does the save schema use stable species IDs and quantized shape data?
- Are the remove and inspect verbs wired to every species from day one?
- Has the team profiled a forest scene with the target hardware, not the lead artist’s desktop?
- Is there a content plan for evergreen species so winter is not a blank map?
If even one of these is open, the team should close it before scaling the catalog. Each open item tends to multiply the cost of every later change.
Frequently asked questions
Are woody plants in Grow a Garden different from regular crops?
They are different at the system level even if the surface UI looks similar. A crop in a typical farming sim has one or two growth stages, a short timer, and a single harvest verb. A woody plant has multiple persistent stages, a long season-scale timer, a separate set of tools (axe, shears, scythe), and a state that has to survive across sessions. The catalog entry, the growth simulator, the interaction layer, and the renderer all need to treat it as its own object type, not as a slow crop.
Do small teams need a custom engine to ship woody plants well?
No. The same patterns work in Unity, Unreal, Godot, or a custom stack, because the heavy lifting is in the data layer and the LOD groups, not in engine-specific features. The team that locks the catalog, the growth update, and the LOD budget will ship a believable forest in any of the major engines. The team that skips the data layer will fight the engine, no matter which one it picks.
How many species of woody plants should a first release include?
For a small studio, four to six fruit trees, three to five shrubs, and one hedge type per biome is a defensible first cut. The mistake is to over-fill the catalog before the core loop is fun. Variety is content, but the growth and interaction systems are the product. Add species once the systems are stable, and treat each biome as a vertical slice that reuses the same code.
How do we keep performance stable as the forest grows?
Sort every woody plant into hero, mid, and background LOD groups, share materials across species, use GPU instancing for hedges and background trees, and stream the catalog with the same priority as terrain tiles. The biggest win is usually to move background trees to a static shadow cascade so they do not contribute to the dynamic shadow pass. Profile with a representative build on target hardware, not on the lead artist’s machine, and budget the woody plant set to roughly 20-30 percent of draw calls.
When should the team add a pruning system?
If pruning is in the design document at all, the data shape has to be in the catalog from day one, even if the player-facing tool ships later. Adding pruning late usually means re-exporting meshes and rewriting the save schema, both of which are expensive in late production. A minimal pruning system with one hedge, three shape presets, and a yield modifier is enough to validate the loop, and the team can extend it to fruit trees in a later content update.
Do woody plants need unique wind animations?
No. A single global wind vector, applied through a shared shader with per-species parameters for trunk stiffness and leaf amplitude, is enough. The visual variety comes from the species parameters in the catalog, not from a unique shader per tree. Per-vertex noise on every leaf is one of the most common GPU wastes in a forest scene, and almost always unnecessary.
What is the cheapest way to make a forest feel alive in winter?
Keep at least one evergreen species per biome and let the season tint shader use a winter palette that desaturates the leaves without removing the silhouette. A world with bare branches and a few green pines reads as winter at a glance, without any new meshes. A second cheap touch is to keep hedges full through winter, because hedges are usually the player’s path markers and losing them makes navigation harder.
Can woody plants be added after launch without breaking saves?
Yes, if the save schema carries stable species IDs and re-derives the visual stage on load. New species can be added to the catalog and shipped in a content update, and existing saves will simply not include the new entries. The risky case is when the save schema uses mesh names or material paths instead of species IDs. A save that says “tree_atlas_03” will break the moment the art team renames the asset, so the rule is to keep IDs in data, not in filenames.
How do we keep the save file from ballooning in a forest-heavy world?
Quantize the pruning grid, cap the per-plant data size in the catalog, and avoid storing per-vertex state. A few hundred trees with a 4×4 trim grid each is a few kilobytes of JSON, which is fine. A few hundred trees with per-leaf state is megabytes, which is not. The same rule applies to season tint: derive the tint on load from the planted day, do not store a per-frame color.
What is the single highest-leverage decision for woody plants?
Locking the catalog data shape before art starts. Almost every later problem in a woody plant system traces back to a field that was not in the catalog on day one, from pruning shape to season tint anchors to harvest verb. A two-day data modeling session up front saves weeks of rework in art, engineering, and QA. The team that writes the catalog first ships the forest.