Tree Grow – Dev Diary 1

Tree Grow A Unity 2D Project – 3rd to 10th of November 2021

Formulation of the Idea

This whole adventure started more so as a joking dare from a friend. I was watching a YouTube video and wanted to play the game, my friend just sad “Well why don’t you make it?”. With this log I’m sure you can see what I chose to do.

I take no credit for the game idea, as stated this is just my attempt to create something I saw. So, what is it? Tree grow is simply a tree that will grow based on random ball bouncing and landing in trays. Kind of like ‘Plinko’, except the tree would be facing an opponent that would be doing the same. One of the trays would cause fruit to grow on the tree, while another tray would cause this fruit to be flung at the other tree dealing damage. The goal being to destroy the other tree’s “root”, basically just the starting node of the tree. What does the player do? Pick a tree to win, sit back and watch as the two trees fight to win.

Thus, began my coding journey with Unity as my engine and Visual Studio 2019 as my IDE. A new Unity 2D project began, under the humble name of “Tree Grow”

Where’d it start?

With all the design of the game said and done, as it’s completely based off the video. All I had to make it. So I broke it down into its core parts. This allowed for easy prioritization and scheduling, as I knew what tasks required other tasks. With this I knew the basics of what I needed to do, and what I should start with.

  • Tree growing
  • Growing from random ball bouncing
  • Tree could branch, which would cause a split
  • Tree could grow, which would just add to the tree
  • The tree would attack a rival tree via grown fruits

The Basic Tree Code Structure

First was how I wanted the tree feature to work. It wasn’t hard to tell that the ‘tree’ itself and the ‘branch nodes’ would need to be separate classes. I was planning for the nodes to have a “waterfall” type structure (a list with a twist). Where a node would be parent to the nodes directly added after it. Meaning a node would hold a reference to the next node, but also the branching node if a branch command was given.

This meant that adding a new node would require going down the list until it hit a dead end, then performing the requested action on that last node. To ensure that the tree wouldn’t be predictable, if along the “waterfall” command pipeline it hit a branch it would just select one of the branches at random, the go down that route.

This idea was simple and would aid with a future mechanic. It also avoided having one big list with the need to find a specific node and some complex indexing function. There are some downsides to this method, and that is overflowing the heap. While unlikely a big enough tree list would cause a “waterfall” command to put too much onto the heap. However, this shouldn’t be an issue as the trees would be destroyed (by the opposing tree) or just become too big and lag the game into unplayability from physics updates.

The tree is designed with expansion in mind. I’ve done this by having a tree interface with important shared methods. such as “Grow”, “Branch” and “Scale”. This would allowed for important functions to be called from external scripts without needing references to specific classes.

Both the tree node and base use the interface. With the node doing the “waterfall” while the base’s implementation was used to call the first’s nodes implementation starting the “waterfall”. If you look at the image above, the parent can both be the tree base and tree node, while children are always nodes.

The First Problem

Tree physics. I didn’t think I would have to sit down for hours playing around with small values think “Does this make it more tree like?”. Well I had to. A fair amount of hours was spend playing around with how the tree would have it’s physics handled. This ranged from what it’s physics would actually be and then trying to reduce the impact on frames that method would have.

After a while I decided to go with Unity 2D spring. This allowed me to keep two nodes together with a force while allowing for them to move around slightly. I also added a Unity 2D hinge joint to assure the tree would only bend so much. I disabled parent child collisions, as they now had rigid body components and the two colliding was just ugly.

The result
The node setup

However, no matter what I changed the values to the tree would always just crumble. I spent a few hours looking into both of the Unity components thinking I was missing something, and fiddling with values. Nothing worked. So I moved on.

The issue was the nodes would just rotated too far. Simple solution, stop rotation. It worked, but since the rotation was now locked, the hinge joint did nothing, so I removed it. The tree now grew upwards, and upwards and then started to freak-out. With no rotation the tree struggled to not collide with other branches. Another simple solution, lock rotation only when not colliding. This allowed the tree to bend and flex to move out of the way of other branches while not flopping on the floor.

A Slight Touch

With the tree now growing on command. All that was needed was a slight touch. I setup a small ‘Plinko’ board with two Trays that would grow and branch the tree. Then, I watched as the tree grew. The only issue being the new nodes just appeared. In the original video, you could see the new nodes work their way up the tree via highlighted nodes before they appeared.

This took a bit to implement, as the “waterfall” command structure I had setup was built inside a loop, meaning it couldn’t just pause. I already knew about IEnumerator functions in Unity, but was hoping I could return a “TreeNode” from one of them. While interesting this endeavour led no where. Thus, I rewrote the “waterwall” command structure.


The old code (On the tree/base):

        /// <summary>
        /// Gets the end node of the tree;
        /// </summary>
        /// <returns>The last node of a random branch</returns>
        /// <remarks>Instantly returns a random end node of the tree</remarks>
        private TreeNode GetEndNode()
        {
            //Temp nodes used for checking
            TreeNode checkingNode = m_baseNode;
            TreeNode affectingNode = m_baseNode;

            //Goes until the checking node is == null, meaning it's hit an end
            while (checkingNode != null)
            {
                //Gets the next node
                checkingNode = affectingNode.GetNextNode();

                //If the next node exists make set it as the affecting node
                if (checkingNode != null)
                {
                    affectingNode = checkingNode;
                }
            }

            //Returns the found end node
            return affectingNode;
        }

The new code (On the node itself):

        /// <summary>
        /// Cause a tree node to grow or branch
        /// </summary>
        /// <param name="waitTime">The time to keep this node highlighted</param>
        /// <param name="grow">Whether or not this will grow or branch</param>
        /// <returns>The time the system needs to wait</returns>
        public IEnumerator ExpandWait(float waitTime, bool grow)
        {
            //Highlights the node
            m_refrencedTimes++;
            m_spriteRenderer.color = m_highlightColour;

            yield return new WaitForSeconds(waitTime);

            //Unhighlights the node
            m_refrencedTimes--;
            if (m_refrencedTimes <= 0)
            {
                m_spriteRenderer.color = m_baseColour;
            }

            //Checks if this node needs to grow or if it needs to send the down the chain
            TreeNode tempNode = GetNextNode();
            if (tempNode == null)
            {
                //Checks if the node should grow or brnach
                if (grow)
                {
                    Grow();
                }
                else
                {
                    Branch();
                }
            }
            else
            {
                tempNode.StartCoroutine(tempNode.ExpandWait(waitTime, grow));
            }
        }

GetNextNode() function:

        /// <summary>
        /// Gets the next node down the line, if the node branches will randomly return the node
        /// </summary>
        /// <returns>The next node down this path, or null if end node</returns>
        public TreeNode GetNextNode()
        {
            //Checks if a branching node
            if (m_branchNode == null)
            {
                //Checks if end node
                if (m_node == null)
                {
                    //Is end node
                    return null;
                }
                else
                {
                    //Not end node
                    return m_node;
                }
            }
            else
            {
                //Has two node, so pick one at random and return it
                return HelperFunctions.GenerateRandomValue(0, 2) == 0 ? m_node : m_branchNode;
            }
        }

Where it’s at Now

While progress has been made, there’s still a bit to go. I want to look further into improving physics, as the game still lags when it reaches the stage of big trees. The ‘Plinko’ board needs some work added to it. I want a design tool that will auto space ‘x’ trays into 100% with each tray taking ‘y’%. This would just allow for me to use the inspector to adjust the trays size easily and not fiddle around too much. I’m really aiming to put the hard work in early so later on it’s easier.

What core features still need implimenting

  • Attacking with grown fruit
  • Spawning from random ball bounce.

While there’s a ‘Planko’ board is random ball bounce, if you watched the original video you’d notice that my ‘Planko’ board falls very short of the targeted mark. It will require a bit of reworking before I’m happy with it.

The current stage of Tree Grow

Leave a Comment

Your email address will not be published. Required fields are marked *