The Secret Blue Forest

Full lifecycle production from initial concept to release on Steam.

The Secret Blue Forest is a puzzle-adventure game developed entirely from the ground up in Unity. Serving as the sole programmer and designer, I architected the core gameplay loops, custom physics interactions, and enemy AI, managing the entire production pipeline through to a public launch. The project required balancing scalable, performant systems with responsive game feel, specifically focusing on spatial puzzles and combat encounters.


Core Contributions
  • Recursive Puzzle Mechanics: Engineered modular spatial boundary checks utilizing dynamic object scaling. This allowed for chained, Sokoban-style block-pushing interactions, enabling the player to manipulate multiple stacked physical objects simultaneously.
  • State-Driven Enemy AI: Developed dynamic decision trees for enemy behavior based on spatial proximity. Implemented weighted Random Number Generation to organically adjust an enemy's aggression state
  • End-to-End Deployment: Managed the complete technical lifecycle, moving from raw prototype to commercial build. This included memory management, audio coroutine sequencing, and integration with the Steamworks backend for final storefront distribution.

                            public bool PushedMovement(int side, bool sprint)
                            {
                                this.touch = false;
                                float speedMult = sprint ? 1.8f : 1f;

                                if (this.player != null)
                                {
                                    switch (side)
                                    {
                                        case 0: this.WallCheck(transform.lossyScale.x / 2f, transform.lossyScale.y / 2f, transform.lossyScale.z / 2f, -transform.forward); break;
                                        case 1: this.WallCheck(transform.lossyScale.z / 2f, transform.lossyScale.y / 2f, transform.lossyScale.x / 2f, -transform.right); break;
                                        case 2: this.WallCheck(transform.lossyScale.z / 2f, transform.lossyScale.y / 2f, transform.lossyScale.x / 2f, transform.right); break;
                                        case 3: this.WallCheck(transform.lossyScale.x / 2f, transform.lossyScale.y / 2f, transform.lossyScale.z / 2f, transform.forward); break;
                                    }
                                }

                                if (this.carryBox != null && !this.touch)
                                {
                                    this.carryBox.GetComponent().PushedMovement(side, sprint);
                                    if (this.carryBox.GetComponent().GetTouch()) this.touch = true;
                                }

                                if (!this.touch)
                                {
                                    if (!this.pushSound) StartCoroutine(this.PushSoundRoutine());

                                    Vector3 moveDir = Vector3.zero;
                                    if (side == 0) moveDir = -transform.forward;
                                    else if (side == 1) moveDir = -transform.right;
                                    else if (side == 2) moveDir = transform.right;
                                    else if (side == 3) moveDir = transform.forward;

                                    transform.Translate(moveDir * 4f * speedMult * Time.deltaTime, Space.World);
                                }
                                return this.touch;
                            }
                            
Interactive Physics & Recursion: C# logic driving environmental puzzle mechanics. Handles dynamic boundary checking using object scale, manages sprint state multipliers, and utilizes recursive method calls to allow the player to push multiple stacked or chained physical objects simultaneously.

                            public void CheckNextMove()
                            {
                                if (!this.alive) return;

                                Vector3 playerDirection = (this.Player.transform.position - transform.position).normalized;
                                float turnDirection = Mathf.Abs(Vector3.SignedAngle(transform.forward, playerDirection, Vector3.up));

                                if (this.playerDistance > 180f)
                                {
                                    this.anim.SetInteger("condition", 0);
                                    this.attacking = false;
                                    this.Player.GetComponent().SetDangerMusic(0);
                                    return;
                                }

                                if (this.stats.GetHealth() < this.maxHealth / 1.6f && !this.anim.GetBool("damaged"))
                                {
                                    this.anim.SetBool("damaged", true);
                                    this.anim.SetInteger("condition", 5);
                                    return;
                                }

                                // Distance is <= 180f. Weighted RNG for attack type based on proximity.
                                this.headbutt = this.playerDistance < 70f ? Random.Range(0, 5) >= 3 : Random.Range(0, 5) == 0;
                                this.anim.SetInteger("condition", 1);
                            }
                            
Dynamic AI Decision Handling: Evaluates spatial proximity and current health thresholds to dictate enemy behavior. Implements weighted RNG to dynamically adjust attack aggressiveness based on the player's distance, ensuring varied combat encounters.