Architecture Overview
The system consists of three components:- PowerUp - Abstract base class defining the powerup interface
- JumpBoost - Concrete implementation that increases jump height
- PowerUpPickUp - GameObject component that applies powerups on collision
ScriptableObjects are asset files that store data independently of scenes. This pattern allows you to create multiple powerup variants (e.g., “Small Jump Boost”, “Large Jump Boost”) as reusable assets.
PowerUp Base Class
The abstract base class that all powerup types must inherit from.Implementation
Powerup.cs:3-6
Design Pattern
This uses the Template Method pattern:PowerUpdefines the interface (theApplymethod)- Concrete implementations (like
JumpBoost) provide specific behavior PowerUpPickUpcan work with anyPowerUpsubclass polymorphically
By inheriting from
ScriptableObject instead of MonoBehaviour, powerup definitions exist as assets, not scene objects. This allows reusability across scenes and prefabs.JumpBoost Implementation
A concrete powerup that increases the player’s jump height.Configuration
Multiplier applied to the player’s jump height (1.5 = 50% increase)
CreateAssetMenu Attribute
JumpBoost.cs:3
- Right-click in Project window
- Navigate to Create → Power Ups → Jump Boost
- A new JumpBoost asset is created
Apply Implementation
JumpBoost.cs:8-14
How It Works
- Component Check - Uses
TryGetComponentto safely check if the target has aPlayerJumpcomponent - Multiply Jump Height - Increases the
JumpHeightby the multiplier - Permanent Effect - The jump height remains increased for the rest of the game
TryGetComponent is more efficient than GetComponent because it combines existence checking and component retrieval in one call.PowerUpPickUp Component
The GameObject component that detects player collision and applies the powerup effect.Configuration
The ScriptableObject asset defining which powerup to apply (e.g., a JumpBoost asset)
Implementation
PowerUpPickUp.cs:3-16
Collision Detection
The component:- Checks for player - Uses
TryGetComponent<PlayerJump>to verify the colliding object is the player - Applies effect - Calls the
Applymethod on the assigned powerup asset - Disables pickup - Deactivates the GameObject (can be reactivated later if needed)
Using
SetActive(false) instead of Destroy() allows powerups to be reused through object pooling or respawn mechanics.Creating New Powerups
The system is designed for easy extension. Here’s how to create new powerup types:Example: Speed Boost
Example: Invincibility
Example: Double Points
Setting Up Powerups in Unity
Step 1: Create the ScriptableObject Asset
- Right-click in the Project window
- Select Create → Power Ups → Jump Boost
- Name it (e.g., “JumpBoost_Medium”)
- In the Inspector, set
JumpMultiplierto desired value (e.g., 1.5)
Step 2: Create the Pickup GameObject
- Create a new GameObject in the scene (e.g., “JumpBoostPickup”)
- Add a SpriteRenderer with an appropriate sprite
- Add a 2D Collider (Circle or Box)
- Check Is Trigger
- Add the PowerUpPickUp component
- Drag the JumpBoost asset into the
effectfield
Step 3: Create Multiple Variants
Create different variants by duplicating the asset:- JumpBoost_Small -
JumpMultiplier = 1.2(20% increase) - JumpBoost_Medium -
JumpMultiplier = 1.5(50% increase) - JumpBoost_Large -
JumpMultiplier = 2.0(100% increase)
Integration with Player System
The powerup system integrates seamlessly with the player system:The system uses
PlayerJump as the player identifier. Any GameObject with a PlayerJump component is treated as the player.Advanced Patterns
Stacking Powerups
To allow multiple powerups to stack:Powerup with Visual Feedback
Powerup with Audio
Best Practices
- Use descriptive asset names - Name assets like “JumpBoost_Large” not “JumpBoost1”
- Create asset variants - Make multiple ScriptableObject instances with different values for variety
-
Fail safely - Always use
TryGetComponentto handle cases where the target doesn’t have required components - Consider temporary effects - Use coroutines for time-limited powerups
- Visual feedback - Add particle effects or sound when powerups are collected
- Balance carefully - Test multiplier values to ensure powerups are impactful but not overpowered
-
Document in Inspector - Use
[Tooltip]attributes to explain what each parameter does - Reusability - Design powerups to be reusable across different scenes and game modes
Advantages of ScriptableObject Pattern
- Designer-friendly - Non-programmers can create powerup variants
- Memory efficient - Assets are shared, not duplicated per instance
- Easy balancing - Change values in assets without touching code
- Version control - Assets are text files, easy to track changes
- Runtime independence - Assets exist outside scenes, surviving scene changes
- Polymorphism -
PowerUpPickUpworks with anyPowerUpsubclass