Architecture Overview
The score system consists of four interconnected components:- ScoreSystem - Central score tracking with event broadcasting
- Coin - Individual collectible items that trigger score events
- ScoreUpdate - UI component that displays current score in real-time
- ShowFinalScore - Displays the final score on game over screens
This system uses C# events for communication, creating a loosely coupled architecture where UI and gameplay logic remain independent.
ScoreSystem
The core component that manages score state and coordinates between coin collection and UI updates.Properties
Current score during active gameplay
Static property storing the final score after game completion or death
Events
ScoreSystem.cs:9
Event Subscriptions
The system subscribes to game events during its lifecycle:ScoreSystem.cs:11-23
Proper event cleanup in
OnDisable() prevents memory leaks and ensures events don’t fire after the object is destroyed.Score Update Logic
When a coin is collected, the score is updated and broadcast:ScoreSystem.cs:25-29
?.) safely invokes the event only if there are subscribers.
Final Score Recording
The score is saved to the staticFinalScore property when the game ends:
ScoreSystem.cs:31-34
Using a static property allows the final score to persist across scene changes, making it accessible on game over or victory screens.
Coin
Represents collectible coins in the game world that trigger score updates when collected.Configuration
Point value awarded when this coin is collected
Coin Collection Event
Coin.cs:7
Collision Detection
Coin.cs:9-13
- The
OnCoinCollectedevent is broadcast with this coin instance - The coin GameObject is destroyed
Coins use trigger colliders (non-physical) so they don’t affect player movement while still detecting overlap.
Creating Different Coin Types
You can create coins with different values:ScoreUpdate
UI component that displays the current score in real-time during gameplay.Implementation
ScoreUpdate.cs:4-27
How It Works
- Component Reference - Gets the
Textcomponent inAwake() - Event Subscription - Subscribes to
OnScoreUpdatedwhen enabled - Text Update - Updates the UI text whenever the score changes
- Cleanup - Unsubscribes when disabled
This component can be attached to any GameObject with a
Text component. Multiple instances can exist to show the score in different locations.ShowFinalScore
Displays the final score on game over or victory screens.Implementation
ShowFinalScore.cs:4-13
How It Works
UnlikeScoreUpdate, this component reads the static FinalScore once during initialization:
- Gets the
Textcomponent reference - Reads
ScoreSystem.FinalScore - Formats and displays the final score
This component should be placed on game over or victory scene UI elements. It reads the score once and doesn’t update dynamically.
Event Flow Diagram
Here’s how the events flow through the system:Integration Example
Scene Setup
Creating Custom Score Sources
You can create other collectibles that award points:Best Practices
-
Always unsubscribe - Match every
+=with a-=inOnDisable()to prevent memory leaks -
Use null-conditional operators - Always use
?.Invoke()when firing events to handle cases with no subscribers -
Pass relevant data - Events like
OnCoinCollectedpass the coin instance, allowing access to coin-specific properties -
Static for persistence - Use static properties like
FinalScorewhen data needs to survive scene changes - Single responsibility - Keep each component focused: ScoreSystem tracks, Coin collects, UI components display
- Extensibility - The event-driven design makes it easy to add new score sources or score listeners without modifying existing code
Advantages of Event-Driven Architecture
- Decoupling - UI doesn’t need references to gameplay objects
- Flexibility - Easy to add new score sources or displays
- Testability - Components can be tested independently
- Maintainability - Changes to one component rarely affect others
- Multiple listeners - Many UI elements can react to the same score change