Back To Home

OOPS

18-03-2024


Don't Get Lost in the Code: Mastering Abstraction for Cleaner Unity Development

"Ever feel like your code is a tangled mess of functions and variables, making it hard to understand what's actually happening? You might be drowning in the details and missing the bigger picture. Abstraction is your life vest in this code ocean, helping you focus on the essentials and leave the complexities below the surface!"

Introduction :

  1. Abstraction plays a crucial role in computer science, allowing us to separate essential features from implementation details.

  2. In simple terms, abstraction hides the complexity of a system's inner workings and presents only the necessary information to users. Users are concerned with "what it does" rather than "how it does it."

Here's a real-life comparison:

  1. Imagine you have a special remote control for your TV. You just press buttons on it, right? But do you know how it actually works inside? Nope, and you don't need to! Abstraction hides all the tricky parts, like how the remote talks to the TV, and just lets you focus on changing channels or adjusting volume.

  2. It's the same with your smartphone. You tap on icons to play games or send messages, but you don't need to worry about how the phone's brain works behind the scenes.

  3. Even when you go to the ATM with your parents, you just press buttons to get money or check your balance. You don't have to understand how the machine counts your money or keeps track of your account.

  4. An iceberg floating in water. The tip of the iceberg represents the visible gameplay mechanics (jumping, attacking). The submerged part of the iceberg represents the complex code implementing those mechanics, hidden by abstraction layers.

  5. post 2

    In C# and Unity :

  6. In C# and Unity programming, abstraction is achieved through abstract classes and interfaces. we use it to create tools that are easy for us to use without needing to know all the complicated details.

  7. An abstract class serves as a blueprint that cannot be directly instantiated but can be used as a base for other classes. Abstract classes may define abstract methods—methods without implementation that must be defined by derived classes. Additionally, abstract classes may contain non-abstract methods.

  8. The purpose of abstract classes is to provide foundational functionality and common features shared by multiple derived classes. They facilitate code organization and promote reusability by allowing derived classes to implement specific functionalities while inheriting common behavior from the abstract class.

The Benefits of Abstraction :

  1. Code Reusability :
    By defining common functionalities in reusable abstractions (interfaces or abstract classes), you can avoid code duplication and enhance maintainability.

  2. Polymorphism :
    Abstraction allows objects of different classes to be treated in a uniform manner if they implement the same abstraction. This enables writing more generic code that can work with a wider range of objects.

  3. Improved Maintainability :
    By separating interfaces and abstract classes from concrete implementations, you can readily modify the underlying mechanisms without impacting code that interacts with the abstraction.

Abstraction Through Interfaces and Abstract Classes :

C# offers two primary tools for achieving abstraction: interfaces and abstract classes.

  1. Interfaces :
    Interfaces define a contract outlining a set of functionalities (methods and properties) that any class implementing the interface must provide. Interfaces themselves don't provide implementations; they dictate what needs to be implemented. click here for more info.

  2. Abstract Classes :
    Abstract classes function as blueprints that define common functionalities (methods and properties) some of which can be implemented directly within the abstract class (non-abstract methods), while others are left abstract (without implementation). Derived classes inheriting from the abstract class must provide implementations for all abstract methods.

Choosing the Right Tool :

  1. Use interfaces for a common set of functionalities across unrelated classes.

  2. Use abstract classes for a natural class hierarchy with shared base functionality and when you want to provide some base implementation for common methods that can be reused by derived classes.

Let's check some example:

    1. GameController example :

  1. Imagine controlling your game with a simple controller. You press "jump," your character soars. But beneath the buttons, a complex code orchestra plays - calculations, animations, all hidden by abstraction.

  2. post 2

2. Character Controller example :

    Character Class :

  1. We start by creating an abstract class called Character. This class has some common properties like health and speed, and it has two methods: Attack() and Move(). The Attack() method is left abstract, meaning each type of character or enemy will have its own way of attacking, while the Move() method is already defined for all characters to move around.

  
public abstract class Character : MonoBehaviour
{
    public float health;
    public float speed;

    // Abstract method
    public abstract void Attack();

    // Non-abstract method
    public void Move()
    {
        // Move the character based on the current speed
    }
}    
            

    Enemy Class :

  1. We then create a subclass of Character called Enemy. This class overrides the abstract Attack() method to define how this specific enemy attacks.

  
public class Enemy : Character
{
    public override void Attack()
    {
        // Implement the attack logic for this enemy
    }
}

    GameController Usage :

  1. In our GameController class, we have a variable called currentCharacter of type Character. We can assign different types of characters or enemies to this variable. In the Start() method, we create a new Enemy instance and assign it to currentCharacter. Then, we can call the Attack() and Move() methods on currentCharacter.

  
public class GameController : MonoBehaviour
{
    public Character currentCharacter;

    void Start()
    {
        currentCharacter = new Enemy();
        currentCharacter.Attack();
        currentCharacter.Move();
    }
}
            

  1. By using abstraction with abstract classes, we create a common interface for different types of characters or enemies. This makes it easier to manage them in our game, while still allowing each type to have its own unique behavior for things like attacking.

Let's check another example:

  1. Power Up : We can use abstraction in C# Unity to create power-ups that enhance our game characters in different ways.

  2. PowerUp Class :

  3. We start by creating an abstract class called PowerUp. This class has a property called duration and two methods: Activate() and Deactivate(). The Activate() method is abstract, meaning each type of power-up will have its own way of activating, while the Deactivate() method is already defined for all power-ups to deactivate them.

  
public abstract class PowerUp : MonoBehaviour
{
    public float duration;

    // Abstract method
    public abstract void Activate();

    // Non-abstract method
    public void Deactivate()
    {
        // Deactivate the power-up
    }
}
              

    SpeedBoost Class :

  1. We then create a subclass of PowerUp called SpeedBoost. This class adds a property called speedMultiplier and overrides the Activate() method to increase the player's speed based on the speedMultiplier.

  
public class SpeedBoost : PowerUp
{
    public float speedMultiplier;

    public override void Activate()
    {
        // Increase the speed of the player based on the speedMultiplier
    }
}          
            

    PlayerController Usage :

  1. In our PlayerController class, we have a variable called currentPowerUp of type PowerUp. When the player collides with a game object tagged as "PowerUp", we assign the PowerUp component of that object to currentPowerUp. Then, we call the Activate() method on currentPowerUp to activate the power-up. When the player exits the collider of the power-up, we call the Deactivate() method to deactivate it.

  
public class PlayerController : MonoBehaviour
{
    public PowerUp currentPowerUp;

    void OnTriggerEnter(Collider other)
    {
        if (other.CompareTag("PowerUp"))
        {
            currentPowerUp = other.GetComponent();
            currentPowerUp.Activate();
        }
    }

    void OnTriggerExit(Collider other)
    {
        if (other.CompareTag("PowerUp"))
        {
            currentPowerUp.Deactivate();
            currentPowerUp = null;
        }
    }
}       
           

  1. By using abstraction with abstract classes, we create a common interface for different types of power-ups. This allows us to easily manage and use them in our game, while still allowing each type of power-up to have its own unique functionality.

Conclusion :

"Using abstraction, we've created a way to make our game characters and power-ups super cool and easy to use! With special blueprints called abstract classes, we can give our characters special powers like flying or super speed, and we can make awesome power-ups like magic potions or speed boosts. By keeping things simple and organized, we can have even more fun playing and creating our games in Unity! So let's keep coding and making our games even more amazing!"

I hope you found this blog post enjoyable!


More Blogs

See All