Developing Flappy Fusion - A Collaborative Unity Game Project

Written on April 24, 2024 by ibsanju.

Last updated April 05, 2025.

See changes
8 min read
––– views

Building Flappy Fusion: Our Unity Game Dev Journey

Hey there! 👋 I'm excited to share how our team (Thanush, Dinesh, and myself, Bharath) built "Flappy Fusion" – our modern spin on the classic Flappy Bird game. Let's dive into the nuts and bolts of this project, from organization to code!

What's Flappy Fusion?

Flappy Fusion is exactly what it sounds like – our take on the addictive tap-to-fly mechanic that had everyone hooked a few years back. We've created a colorful world filled with obstacles and unique characters, each team member bringing their own expertise to make this game come alive.

Project Organization: The Unity Way

When working in a team, good organization is absolutely crucial. Here's how we structured our Unity project to keep everything tidy and maintainable:

Smart Folder Structure

Let's start with our folder structure – something that saved us countless headaches during development!

1. Fonts Folder

This is where all typography assets live. Keeping fonts separate makes them easy to find and apply consistently.

Screenshot showing our fonts folder organization

2. Materials Folder

For any looping backgrounds, we use materials with textures applied to them:

// Example usage: We add texture to material objects for elements like
// backgrounds and ground that need to scroll infinitely

Our materials folder containing scrolling background assets

3. Prefabs Folder

This is where reusable game objects like our pipe obstacles live:

Prefab folder where we store our integrated pipe obstacles

4. Scenes Folder

Flappy Bird has only one level, but we've structured our project to accommodate multiple levels if needed:

Scene folder showing our main game level

5. Scripts Folder

The brain of our operation! All project scripts are kept here:

Script folder showing our game's core functionality files

6. Sprites Folder

All visual assets including images and videos are neatly organized here:

Sprites folder containing our game's visual elements

Note: Having this clear folder structure was absolutely essential for our team collaboration. It prevented asset conflicts and made it easy for everyone to find what they needed!

The Code Behind Flappy Fusion

Now for the fun part – let's look at the key scripts that power our game! I'll break down each one with explanations.

Game Manager Script

This script controls the overall game state – handling score, UI, and game flow:

using UnityEngine;
using UnityEngine.UI;
 
public class gameManager : MonoBehaviour
{
    public player player;             // Reference to our player script
    public Text scoreText;            // UI element for displaying score
    public GameObject playButton;     // UI button to start the game
    public GameObject gameOver;       // Game over UI panel
 
    private int score;                // Player's current score
 
    private void Awake() {
        Application.targetFrameRate = 60;  // Lock to 60fps for consistent gameplay
        Pause();                           // Start in paused state
    }
 
    public void Play() {
        // Reset game state
        score = 0;
        scoreText.text = score.ToString();
        playButton.SetActive(false);
        gameOver.SetActive(false);
 
        // Start gameplay
        Time.timeScale = 1f;          // Normal time flow
        player.enabled = true;        // Enable player controls
 
        // Clean up any existing pipes
        pipes[] pipes = FindObjectsOfType<pipes>();
        for (int i = 0; i < pipes.Length; i++) {
            Destroy(pipes[i].gameObject);
        }
    }
 
    public void Pause() {
        Time.timeScale = 0f;          // Freeze time
        player.enabled = false;       // Disable player controls
    }
 
    public void GameOver() {
        gameOver.SetActive(true);     // Show game over UI
        playButton.SetActive(true);   // Show play again button
        Pause();                      // Pause the game
    }
 
    public void IncreaseScore() {
        score++;                      // Increment score
        scoreText.text = score.ToString();  // Update UI
    }
}

Parallax Background Script

This creates that smooth scrolling background effect:

using UnityEngine;
 
public class NewBehaviourScript : MonoBehaviour  // Note: Should be renamed to "Parallax"!
{
    private MeshRenderer meshRenderer;
    public float animateSpeed = 1f;   // How fast the background scrolls
 
    private void Awake() {
        meshRenderer = GetComponent<MeshRenderer>();
    }
 
    private void Update() {
        // Shift texture offset based on time to create scrolling effect
        meshRenderer.material.mainTextureOffset += new Vector2(animateSpeed * Time.deltaTime, 0);
    }
}

Pipes Script

This handles the behavior of our obstacles:

using UnityEngine;
 
public class pipes : MonoBehaviour
{
    public float speed = 5f;          // How fast pipes move
    private float leftEdge;           // Screen boundary for cleanup
 
    private void Start() {
        // Calculate the left edge of the screen for pipe removal
        leftEdge = Camera.main.ScreenToWorldPoint(Vector3.zero).x - 8f;
    }
 
    private void Update() {
        // Move pipes leftward continuously
        transform.position += Vector3.left * speed * Time.deltaTime;
 
        // Destroy pipes once they're off-screen
        if(transform.position.x < leftEdge) {
            Destroy(gameObject);
        }
    }
}

Player Script

This is where the magic happens – controls, animation, and collision detection:

using UnityEngine;
 
public class player : MonoBehaviour
{
    private SpriteRenderer spriteRenderer;
    public Sprite[] sprites;          // Array for wing flap animation frames
    private int spriteIndex;          // Current animation frame
    private Vector3 direction;        // Movement direction vector
    public float gravity = -9.8f;     // Gravity strength
    public float strength = 5f;       // Jump/flap strength
 
    private void Awake() {
        spriteRenderer = GetComponent<SpriteRenderer>();
    }
 
    private void Start() {
        // Start sprite animation, repeating every 0.15 seconds
        InvokeRepeating(nameof(AnimateSprite), 0.15f, 0.15f);
    }
 
    private void OnEnable() {
        // Reset position and direction when enabled
        Vector3 position = transform.position;
        position.y = 0f;
        transform.position = position;
        direction = Vector3.zero;
    }
 
    private void Update() {
        // Handle input - keyboard, mouse, or touch
        if (Input.GetKeyDown(KeyCode.Space) || Input.GetMouseButtonDown(0)) {
            direction = Vector3.up * strength;  // Flap upward
        }
 
        if (Input.touchCount > 0) {
            Touch touch = Input.GetTouch(0);
            if (touch.phase == TouchPhase.Began) {
                direction = Vector3.up * strength;  // Flap on touch
            }
        }
 
        // Apply gravity and move the player
        direction.y += gravity * Time.deltaTime;
        transform.position += direction * Time.deltaTime;
    }
 
    private void AnimateSprite() {
        // Cycle through wing flap animation frames
        spriteIndex++;
        if (spriteIndex >= sprites.Length) {
            spriteIndex = 0;
        }
        spriteRenderer.sprite = sprites[spriteIndex];
    }
 
    private void OnTriggerEnter2D(Collider2D other) {
        // Handle collisions
        if (other.gameObject.tag == "Obstacle") {
            FindObjectOfType<gameManager>().GameOver();  // Game over on pipe hit
        } else if (other.gameObject.tag == "Score") {
            FindObjectOfType<gameManager>().IncreaseScore();  // Increment score on passing
        }
    }
}

Spawner Script

This creates our endless stream of pipe obstacles:

using UnityEngine;
 
public class spawner : MonoBehaviour
{
    public GameObject prefab;         // Pipe prefab to spawn
    public float spawnRate = 1f;      // How often to spawn pipes
    public float minHeight = -1f;     // Minimum vertical position
    public float maxHeight = 1f;      // Maximum vertical position
 
    private void OnEnable() {
        // Start spawning pipes at regular intervals
        InvokeRepeating(nameof(Spawn), spawnRate, spawnRate);
    }
 
    private void OnDisable() {
        // Stop spawning when disabled
        CancelInvoke(nameof(Spawn));
    }
 
    private void Spawn() {
        // Create a new pipe at random height
        GameObject pipes = Instantiate(prefab, transform.position, Quaternion.identity);
        pipes.transform.position += Vector3.up * Random.Range(minHeight, maxHeight);
    }
}

See It In Action!

Check out our game in action:

Demo video showing Flappy Fusion gameplay

Try It Yourself

Want to give our game a spin? Download it here:

Key Learnings from This Project

Building Flappy Fusion taught us some valuable lessons:

  1. Clean organization matters - Our folder structure prevented numerous headaches
  2. Component separation works - Each script handles one specific responsibility
  3. Input handling needs multiple options - Supporting keyboard, mouse and touch makes games accessible
  4. Physics don't need to be complex - Simple gravity calculations can create engaging gameplay
  5. Code comments save time - When team members need to understand each other's work

What's Next?

The source code for Flappy Fusion is available upon request. We're also planning future enhancements like:

  • Additional character skins
  • Difficulty settings
  • Power-ups and special abilities
  • Leaderboard integration

That's a wrap on our Flappy Fusion development story! I hope this breakdown gives you some insights whether you're a beginner or experienced Unity developer. If you have any questions about our implementation, feel free to reach out in the comments! 👾

Happy coding!

Share this article

Enjoying this post?

Don't miss out 😉. Get an email whenever I post, no spam.

Subscribe Now