Devlog10: Implement Missions (Story) feature



Plan developed with chat with Claude.io.
I like using Guthub Projects for updates for this sprint - Click here
Reflection:
- my apprentice (Claude.io) was overly enthusiastic and created a system that was too complex for me and didn't work.
- Some progress here with version 2 of above, this commit gives me confidence we are making progress:
- Trouble shooting getting UI to work when transitioning from Main Menu to Story mode. Devlog10 video
- Perseverance pays off - basic version of story mode works - commit feature: Story Mode - basic story complete with polish needed
- Demo4 uploaded to itch.io - tutorial system needs fixing: story mode panel gets in the way.
- I like using spreadsheets for UML style diagrams - see screen shot
First few hours
7Bridges Story System - SOLID Design Architecture
SOLID Principles Application
1. Single Responsibility Principle (SRP)
Each class has one reason to change:
StoryManager
→ Story progression logic onlyDialogueSystem
→ Dialogue display onlyHistoricalContext
→ Historical facts onlyEulerNPC
→ Euler character behavior only
2. Open/Closed Principle (OCP)
Open for extension, closed for modification:
IStoryElement
interface allows new story types without changing existing codeStoryMissionFactory
can create new mission types- Abstract
StoryMission
base class for common behavior
3. Liskov Substitution Principle (LSP)
Derived classes must be substitutable:
- Any
StoryMission
can replaceMissionDefinition
- Any
IStoryElement
can be used interchangeably KonigsbergMission
is-aStoryMission
4. Interface Segregation Principle (ISP)
Clients don't depend on unused interfaces:
IDialogueProvider
separate fromIStoryProgression
IHistoricalNarrator
separate fromINPCBehavior
- Small, focused interfaces
5. Dependency Inversion Principle (DIP)
Depend on abstractions, not concretions:
StoryManager
depends onIStoryElement
, not concrete classesDialogueSystem
depends onIDialogueProvider
- Dependency injection through constructors/properties
UML Class Diagram
classDiagram %% Existing System (Simplified) class LearningMissionsManager { -MissionDefinition[] missions +StartMission(int index) +GetCurrentMissionIndex() } class MissionDefinition { +string missionName +JourneyType targetType +string learningObjective } %% New Story System class IStoryElement { <<interface>> +string StoryId +bool IsComplete +void Initialize() +void Execute() +void Complete() } class StoryManager { -IStoryElement[] storyElements -IDialogueSystem dialogueSystem -IHistoricalContext historicalContext +void StartStory() +void ProgressStory() +void ShowDialogue(string text) } class DialogueSystem { -TextMeshProUGUI dialogueText -Button continueButton +void ShowDialogue(string text) +void HideDialogue() +event Action OnDialogueComplete } class IDialogueProvider { <<interface>> +string[] GetDialogue(string context) +string GetIntroduction() +string GetConclusion() } class EulerNPC { -Vector3 position -Animator animator +void Appear() +void Speak(string dialogue) +void Disappear() } class StoryMission { <<abstract>> -string storyIntroduction -string historicalContext -EulerNPC euler +abstract void ExecuteStoryPhase() +void ShowIntroduction() +void ShowConclusion() } class KonigsbergMission { -int bridgesCrossed -bool puzzleAttempted +void ExecuteStoryPhase() +void ShowKonigsbergHistory() +void DemonstrateImpossibility() } class HistoricalContextProvider { -Dictionary~string, HistoricalFact~ facts +string GetHistoricalContext(string period) +string GetMathematicalExplanation(string concept) +HistoricalFact GetEulerBiography() } %% Relationships LearningMissionsManager --> MissionDefinition : contains StoryManager --> IStoryElement : manages StoryManager --> DialogueSystem : uses StoryManager --> HistoricalContextProvider : uses StoryMission ..|> IStoryElement : implements StoryMission ..|> IDialogueProvider : implements KonigsbergMission --|> StoryMission : extends EulerNPC ..|> IDialogueProvider : implements DialogueSystem --> IDialogueProvider : uses %% Integration with existing LearningMissionsManager --> StoryManager : delegates to StoryMission --> MissionDefinition : extends
UML Sequence Diagram - Mission Flow
sequenceDiagram participant Player participant UI as LearningMissionsManager participant SM as StoryManager participant DS as DialogueSystem participant Euler as EulerNPC participant JT as JourneyTracker Player->>UI: Start Mission 1 UI->>SM: StartStory("KonigsbergIntro") SM->>DS: ShowDialogue("Welcome to 1736...") DS->>Player: Display introduction Player->>DS: Click Continue DS->>SM: OnDialogueComplete SM->>Euler: Appear() Euler->>DS: ShowDialogue("I am Leonhard Euler...") Player->>DS: Click Continue DS->>SM: OnDialogueComplete SM->>JT: SetMissionType(Walk) SM->>UI: BeginGameplay() loop Gameplay Phase Player->>JT: Move/Cross Bridges JT->>SM: OnProgressUpdate alt Mission Complete SM->>Euler: Speak("Interesting approach...") SM->>DS: ShowConclusion() end end SM->>UI: MissionComplete() UI->>SM: StartStory("NextMission")
Integration Strategy
Extending Existing Classes
// Extend existing MissionDefinition public class StoryMissionDefinition : MissionDefinition { public string storyIntroduction; public string[] eulerDialogue; public string historicalContext; public string conclusionText; } // Extend LearningMissionsManager public partial class LearningMissionsManager { [SerializeField] private StoryManager storyManager; // Override existing method public override void StartMission(int missionIndex) { if (missions[missionIndex] is StoryMissionDefinition storyMission) { storyManager?.StartStoryMission(storyMission); } else { base.StartMission(missionIndex); // Original behavior } } }
Dependency Injection Pattern
public class StoryManager : MonoBehaviour { // Dependencies injected via inspector or constructor [SerializeField] private DialogueSystem dialogueSystem; [SerializeField] private EulerNPC eulerNPC; [SerializeField] private HistoricalContextProvider contextProvider; // Constructor injection for testing public StoryManager(IDialogueSystem dialogue = null, IHistoricalContext context = null) { this.dialogueSystem = dialogue ?? GetComponent<DialogueSystem>(); this.contextProvider = context ?? GetComponent<HistoricalContextProvider>(); } }
Component Diagram
graph TB subgraph "Existing Game Systems" LMM[LearningMissionsManager] JT[JourneyTracker] BS[Bridge System] UI[MinimalModeUI] end subgraph "New Story System" SM[StoryManager] DS[DialogueSystem] HCP[HistoricalContextProvider] ENPC[EulerNPC] end subgraph "Story Content" SMD[StoryMissionDefinition] KM[KonigsbergMission] HC[HistoricalContext] end %% Dependencies LMM --> SM : delegates story missions SM --> DS : displays dialogue SM --> HCP : gets historical facts SM --> ENPC : controls NPC SM --> JT : monitors progress %% Content SM --> SMD : loads story data KM -.-> SMD : implements HCP --> HC : provides facts %% UI Integration DS --> UI : reuses text components SM --> UI : triggers updates style SM fill:#e1f5fe style DS fill:#e8f5e8 style HCP fill:#fff3e0 style ENPC fill:#fce4ec
Implementation Benefits
1. Maintainability (SRP)
- Story logic separated from gameplay logic
- Easy to modify dialogue without affecting game mechanics
- Historical content can be updated independently
2. Extensibility (OCP)
- New story elements can be added without modifying existing code
- Different dialogue providers (Euler, other NPCs, narration)
- New mission types just implement
IStoryElement
3. Testability (DIP)
- Mock interfaces for unit testing
- Story progression can be tested without UI
- Historical content can be validated separately
4. Reusability
- Dialogue system can be used for other educational content
- Historical context provider works for any mathematical history
- Story structure supports other mathematical topics
Quick Implementation Steps
- Create interfaces first (
IStoryElement
,IDialogueProvider
) - Implement simple DialogueSystem (reuse existing UI components)
- Create StoryManager with dependency injection
- Build KonigsbergMission extending existing mission system
- Add EulerNPC with basic dialogue functionality
- Integrate with LearningMissionsManager using composition
This design leverages your existing architecture while adding story capabilities through clean, maintainable OOP principles.
Get 7Bridges
7Bridges
An educational open-world simulation game that teaches graph theory and network concepts.
Status | Released |
Author | andrew-leary |
Genre | Educational, Adventure, Puzzle |
More posts
- Devlog11: Polish MVP Demo5 days ago
- Devlog09: Feature Proposal - Mission7 days ago
- Devlog08: Summary of Code and Documentation7 days ago
- Devlog07: Work Flow12 days ago
- Devlog06: UI cleanup18 days ago
- Devlog05: Cutscene Management19 days ago
- Devlog04: Sprint 4&5 Tutorial System20 days ago
- Devlog03: Sprint 327 days ago
- DevLog02: Sprint234 days ago
Leave a comment
Log in with itch.io to leave a comment.