Add roadmap docs
This commit is contained in:
463
docs/cards_wip/card_migration_strategy.md
Normal file
463
docs/cards_wip/card_migration_strategy.md
Normal file
@@ -0,0 +1,463 @@
|
||||
# Old Card Scripts - Migration Strategy
|
||||
|
||||
## TL;DR: What Happens to Old Scripts?
|
||||
|
||||
**Answer:** They are **REPLACED** by the new state machine system, but **CardDisplay stays**.
|
||||
|
||||
### Keep (Don't Touch) ✅
|
||||
- **`CardDisplay.cs`** - Core visual renderer, used by both old and new systems
|
||||
|
||||
### Replace (Eventually Deprecate) 🔄
|
||||
- **`FlippableCard.cs`** → Replaced by `Card.cs` with state machine
|
||||
- **`AlbumCard.cs`** → Replaced by `CardPlacedInSlotState.cs` + `CardAlbumEnlargedState.cs`
|
||||
- **`AlbumCardPlacementDraggable.cs`** → Replaced by `Card.cs` with `CardDraggingState.cs`
|
||||
|
||||
---
|
||||
|
||||
## Current Usage Analysis
|
||||
|
||||
### Where FlippableCard is Used:
|
||||
1. **BoosterOpeningPage.cs** (8 references)
|
||||
- Line 592: Instantiate FlippableCard for booster reveal
|
||||
- Line 601, 643, 660, 752, 770: GetComponent calls
|
||||
- **Impact:** High - main booster opening flow
|
||||
|
||||
2. **AlbumCardPlacementDraggable.cs** (1 reference)
|
||||
- Line 45: GetComponent reference
|
||||
- **Impact:** Medium - album placement flow
|
||||
|
||||
3. **AlbumCard.cs** (1 reference)
|
||||
- Line 94: GetComponentInParent during click forwarding
|
||||
- **Impact:** Low - will be removed when AlbumCard is replaced
|
||||
|
||||
### Where AlbumCard is Used:
|
||||
1. **AlbumCardSlot.cs** (2 references)
|
||||
- Line 186-187: Instantiate and GetComponent for pre-placed cards
|
||||
- **Impact:** High - album slot system
|
||||
|
||||
2. **AlbumViewPage.cs** (2 references)
|
||||
- Line 346: GetComponent when handling enlarge
|
||||
- Line 457-458: Instantiate AlbumCardPlacementDraggable
|
||||
- **Impact:** High - album view interactions
|
||||
|
||||
3. **CardDisplay.cs** (1 reference)
|
||||
- Line 316: GetComponentInParent for preview mode
|
||||
- **Impact:** Low - preview feature
|
||||
|
||||
4. **FlippableCard.cs** (1 reference)
|
||||
- Line 73: GetComponentInChildren reference
|
||||
- **Impact:** Will be removed when FlippableCard is replaced
|
||||
|
||||
---
|
||||
|
||||
## Migration Phases
|
||||
|
||||
### Phase 1: Parallel Development (Current) ✅
|
||||
**Status:** Both systems coexist, no breaking changes
|
||||
|
||||
```
|
||||
Old System (Active) New System (Being Built)
|
||||
├─ FlippableCard.cs ├─ Card.cs
|
||||
├─ AlbumCard.cs ├─ CardContext.cs
|
||||
├─ AlbumCardPlacement... ├─ CardAnimator.cs
|
||||
└─ CardDisplay.cs ←──────────┼─→ CardDisplay.cs (shared!)
|
||||
└─ State scripts...
|
||||
```
|
||||
|
||||
**Action:** Build new Card prefab, test in isolation
|
||||
**Timeline:** Current (you're here!)
|
||||
|
||||
---
|
||||
|
||||
### Phase 2: Partial Replacement - Booster Opening (Recommended Start)
|
||||
**Status:** Replace booster cards only, album cards still use old system
|
||||
|
||||
#### Changes Required:
|
||||
|
||||
**File: `BoosterOpeningPage.cs`**
|
||||
|
||||
**Old code:**
|
||||
```csharp
|
||||
[SerializeField] private GameObject flippableCardPrefab;
|
||||
|
||||
// In SpawnCards()
|
||||
GameObject cardObj = Instantiate(flippableCardPrefab, cardDisplayContainer);
|
||||
FlippableCard flippableCard = cardObj.GetComponent<FlippableCard>();
|
||||
flippableCard.SetupCard(cardData);
|
||||
flippableCard.OnCardRevealed += HandleCardRevealed;
|
||||
flippableCard.OnCardTappedAfterReveal += HandleCardTapped;
|
||||
```
|
||||
|
||||
**New code:**
|
||||
```csharp
|
||||
[SerializeField] private GameObject cardPrefab; // New Card prefab
|
||||
|
||||
// In SpawnCards()
|
||||
GameObject cardObj = Instantiate(cardPrefab, cardDisplayContainer);
|
||||
StateMachine.Card card = cardObj.GetComponent<StateMachine.Card>();
|
||||
card.SetupForBoosterReveal(cardData, isNew: true);
|
||||
|
||||
// Subscribe to state events (if needed)
|
||||
var flippingState = card.GetStateComponent<StateMachine.States.CardFlippingState>("FlippingState");
|
||||
// Add custom events if needed, or just let state machine handle it
|
||||
```
|
||||
|
||||
**Benefits:**
|
||||
- Test new system in one isolated flow
|
||||
- Booster opening is cleanest use case (no complex album interactions)
|
||||
- Easy to rollback if issues arise
|
||||
|
||||
**Timeline:** 2-4 hours
|
||||
|
||||
---
|
||||
|
||||
### Phase 3: Full Replacement - Album System
|
||||
**Status:** Replace album cards, old system fully deprecated
|
||||
|
||||
#### Changes Required:
|
||||
|
||||
**File: `AlbumCardSlot.cs`**
|
||||
|
||||
**Old code:**
|
||||
```csharp
|
||||
[SerializeField] private GameObject albumCardPrefab;
|
||||
|
||||
// In SpawnPreviewCard()
|
||||
GameObject cardObj = Instantiate(albumCardPrefab, transform);
|
||||
AlbumCard albumCard = cardObj.GetComponent<AlbumCard>();
|
||||
albumCard.SetupCard(cardData);
|
||||
albumCard.SetParentSlot(this);
|
||||
albumCard.OnEnlargeRequested += HandleEnlarge;
|
||||
albumCard.OnShrinkRequested += HandleShrink;
|
||||
```
|
||||
|
||||
**New code:**
|
||||
```csharp
|
||||
[SerializeField] private GameObject cardPrefab; // Same Card prefab as booster
|
||||
|
||||
// In SpawnPreviewCard()
|
||||
GameObject cardObj = Instantiate(cardPrefab, transform);
|
||||
StateMachine.Card card = cardObj.GetComponent<StateMachine.Card>();
|
||||
card.SetupForAlbumSlot(cardData, this);
|
||||
|
||||
// Subscribe to enlarge events (if needed)
|
||||
var albumEnlargedState = card.GetStateComponent<StateMachine.States.CardAlbumEnlargedState>("AlbumEnlargedState");
|
||||
albumEnlargedState.OnEnlargeRequested += HandleEnlarge;
|
||||
albumEnlargedState.OnShrinkRequested += HandleShrink;
|
||||
```
|
||||
|
||||
**File: `AlbumViewPage.cs`**
|
||||
|
||||
Similar changes for handling enlarged cards and backdrop.
|
||||
|
||||
**Timeline:** 4-6 hours
|
||||
|
||||
---
|
||||
|
||||
### Phase 4: Cleanup - Remove Old Scripts
|
||||
**Status:** Old scripts deleted, prefabs archived
|
||||
|
||||
#### Files to Remove:
|
||||
- ❌ `FlippableCard.cs`
|
||||
- ❌ `AlbumCard.cs`
|
||||
- ❌ `AlbumCardPlacementDraggable.cs` (if drag system is integrated)
|
||||
|
||||
#### Files to Keep:
|
||||
- ✅ `CardDisplay.cs` - Still used by new system!
|
||||
- ✅ `AlbumCardSlot.cs` - Updated to use new Card prefab
|
||||
- ✅ `BoosterOpeningPage.cs` - Updated to use new Card prefab
|
||||
- ✅ `AlbumViewPage.cs` - Updated to use new Card prefab
|
||||
|
||||
**Timeline:** 1 hour (after Phases 2-3 are stable)
|
||||
|
||||
---
|
||||
|
||||
## Coexistence Strategy (During Migration)
|
||||
|
||||
### Option A: Gradual Scene-by-Scene (Recommended)
|
||||
Replace one scene at a time:
|
||||
|
||||
```
|
||||
Week 1: Booster Opening Scene
|
||||
└─ Uses new Card.prefab
|
||||
|
||||
Week 2: Album View Scene
|
||||
└─ Uses new Card.prefab
|
||||
|
||||
Week 3: Any other card scenes
|
||||
└─ Uses new Card.prefab
|
||||
|
||||
Week 4: Remove old scripts
|
||||
```
|
||||
|
||||
**Pros:**
|
||||
- Low risk, easy rollback
|
||||
- Test thoroughly at each step
|
||||
- Team can adapt gradually
|
||||
|
||||
**Cons:**
|
||||
- Longer timeline
|
||||
- Maintain both systems temporarily
|
||||
|
||||
---
|
||||
|
||||
### Option B: Big Bang Replacement
|
||||
Replace all at once in one PR/branch:
|
||||
|
||||
```
|
||||
Day 1-2: Update BoosterOpeningPage
|
||||
Day 3-4: Update AlbumViewPage + AlbumCardSlot
|
||||
Day 5: Test everything
|
||||
Day 6: Delete old scripts
|
||||
```
|
||||
|
||||
**Pros:**
|
||||
- Faster completion
|
||||
- No long-term coexistence
|
||||
|
||||
**Cons:**
|
||||
- Higher risk
|
||||
- More testing needed
|
||||
- Harder to rollback
|
||||
|
||||
---
|
||||
|
||||
## Feature Mapping: Old → New
|
||||
|
||||
### FlippableCard → Card with States
|
||||
|
||||
| Old Feature | Old Implementation | New Implementation |
|
||||
|-------------|-------------------|-------------------|
|
||||
| Idle hover | FlippableCard._idleHoverTween | CardIdleState.OnEnterState() |
|
||||
| Click to flip | FlippableCard.OnPointerClick() | CardIdleState.OnPointerClick() |
|
||||
| Flip animation | FlippableCard.FlipToReveal() | CardFlippingState.OnEnterState() |
|
||||
| New card badge | FlippableCard.ShowAsNew() | CardEnlargedNewState (owns badge) |
|
||||
| Repeat progress | FlippableCard.ShowAsRepeat() | CardEnlargedRepeatState (owns bar) |
|
||||
| Tap to dismiss | FlippableCard.OnPointerClick() when waiting | CardEnlargedNewState.OnPointerClick() |
|
||||
|
||||
### AlbumCard → CardPlacedInSlotState + CardAlbumEnlargedState
|
||||
|
||||
| Old Feature | Old Implementation | New Implementation |
|
||||
|-------------|-------------------|-------------------|
|
||||
| Store parent slot | AlbumCard._parentSlot | CardPlacedInSlotState.SetParentSlot() |
|
||||
| Click to enlarge | AlbumCard.OnPointerClick() | CardPlacedInSlotState.OnPointerClick() |
|
||||
| Enlarge animation | AlbumCard.EnlargeCard() | CardAlbumEnlargedState.OnEnterState() |
|
||||
| Shrink animation | AlbumCard.ShrinkCard() | CardAlbumEnlargedState.OnPointerClick() |
|
||||
| Transform tracking | AlbumCard._originalParent, etc. | CardAlbumEnlargedState (same fields) |
|
||||
|
||||
### AlbumCardPlacementDraggable → Card with CardDraggingState
|
||||
|
||||
| Old Feature | Old Implementation | New Implementation |
|
||||
|-------------|-------------------|-------------------|
|
||||
| Drag feedback | AlbumCardPlacement... | CardDraggingState |
|
||||
| Snap to slot | SnapToAlbumSlot() | CardDraggingState.OnDroppedInSlot() |
|
||||
| Flip on drag | Nested FlippableCard | Just use Card with state machine |
|
||||
|
||||
---
|
||||
|
||||
## Events Migration
|
||||
|
||||
### Old Events (FlippableCard)
|
||||
```csharp
|
||||
flippableCard.OnCardRevealed += (card, data) => { };
|
||||
flippableCard.OnCardTappedAfterReveal += (card) => { };
|
||||
flippableCard.OnFlipStarted += (card) => { };
|
||||
flippableCard.OnClickedWhileInactive += (card) => { };
|
||||
```
|
||||
|
||||
### New Events (State-based)
|
||||
```csharp
|
||||
// Option 1: Listen to state machine transitions
|
||||
var flippingState = card.GetStateComponent<CardFlippingState>("FlippingState");
|
||||
// Then add custom events to states if needed
|
||||
|
||||
// Option 2: Poll current state
|
||||
if (card.GetCurrentStateName() == "RevealedState")
|
||||
{
|
||||
// Card was revealed
|
||||
}
|
||||
|
||||
// Option 3: Add custom events to Card.cs that relay from states
|
||||
card.OnCardRevealed += (data) => { };
|
||||
```
|
||||
|
||||
**Note:** Some events may not be needed anymore because state machine handles transitions internally.
|
||||
|
||||
---
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
### Phase 2 Testing (Booster Only)
|
||||
- [ ] Open booster pack
|
||||
- [ ] Cards spawn in IdleState
|
||||
- [ ] Click card triggers flip
|
||||
- [ ] Flip animation plays correctly
|
||||
- [ ] New cards show "NEW CARD" badge
|
||||
- [ ] Repeat cards show progress bar
|
||||
- [ ] Tap dismisses enlarged view
|
||||
- [ ] Multiple cards work simultaneously
|
||||
- [ ] No console errors
|
||||
|
||||
### Phase 3 Testing (Album Added)
|
||||
- [ ] Cards appear in album slots
|
||||
- [ ] Click card in album enlarges it
|
||||
- [ ] Tap enlarged card shrinks it
|
||||
- [ ] Backdrop shows/hides correctly
|
||||
- [ ] Reparenting works (card moves to top layer)
|
||||
- [ ] Card returns to correct slot
|
||||
- [ ] Page flipping doesn't break card state
|
||||
- [ ] No console errors
|
||||
|
||||
### Regression Testing (Both Phases)
|
||||
- [ ] CardDisplay still renders correctly
|
||||
- [ ] Card data persists across states
|
||||
- [ ] Animations are smooth (60fps)
|
||||
- [ ] Click detection works
|
||||
- [ ] No memory leaks (profile with 20+ cards)
|
||||
|
||||
---
|
||||
|
||||
## Rollback Plan
|
||||
|
||||
If new system has issues:
|
||||
|
||||
### During Phase 2 (Booster Only)
|
||||
1. Revert `BoosterOpeningPage.cs` changes
|
||||
2. Re-assign old `flippableCardPrefab` in inspector
|
||||
3. Old system still intact for album
|
||||
|
||||
### During Phase 3 (Album Added)
|
||||
1. Revert `AlbumCardSlot.cs` and `AlbumViewPage.cs`
|
||||
2. Re-assign old prefabs in inspector
|
||||
3. Both systems revert to old
|
||||
|
||||
### After Phase 4 (Old Scripts Deleted)
|
||||
1. Restore old scripts from Git history
|
||||
2. Recreate old prefabs (if not archived)
|
||||
3. Revert consumer scripts
|
||||
|
||||
**Prevention:** Archive old prefabs before deleting!
|
||||
|
||||
---
|
||||
|
||||
## CardDisplay.cs - The Survivor
|
||||
|
||||
**Why CardDisplay is NOT replaced:**
|
||||
|
||||
CardDisplay is a **pure visual renderer**. It:
|
||||
- Takes CardData and displays it
|
||||
- Has no state management
|
||||
- Has no animation logic
|
||||
- Has no interaction logic
|
||||
|
||||
This is **exactly what we want**! The new system uses CardDisplay as-is.
|
||||
|
||||
**Old hierarchy:**
|
||||
```
|
||||
FlippableCard
|
||||
└─ AlbumCard
|
||||
└─ CardDisplay ← renders visuals
|
||||
```
|
||||
|
||||
**New hierarchy:**
|
||||
```
|
||||
Card (state machine)
|
||||
└─ CardDisplay ← same renderer!
|
||||
```
|
||||
|
||||
CardDisplay is already well-designed - it's a "presenter" in the MVP pattern. Keep it!
|
||||
|
||||
---
|
||||
|
||||
## Migration Checklist
|
||||
|
||||
### Preparation
|
||||
- [ ] New Card.prefab created and tested in isolation
|
||||
- [ ] CardAnimationConfig asset created
|
||||
- [ ] All state scripts compiled without errors
|
||||
- [ ] Team aware of upcoming changes
|
||||
|
||||
### Phase 2: Booster Opening
|
||||
- [ ] Update BoosterOpeningPage.cs to use Card.prefab
|
||||
- [ ] Remove FlippableCard references
|
||||
- [ ] Update prefab assignments in inspector
|
||||
- [ ] Test booster opening flow thoroughly
|
||||
- [ ] Fix any issues before proceeding
|
||||
|
||||
### Phase 3: Album System
|
||||
- [ ] Update AlbumCardSlot.cs to use Card.prefab
|
||||
- [ ] Update AlbumViewPage.cs to use Card.prefab
|
||||
- [ ] Remove AlbumCard references
|
||||
- [ ] Update prefab assignments in inspector
|
||||
- [ ] Test album interactions thoroughly
|
||||
- [ ] Test booster→album flow (cards placed after opening)
|
||||
|
||||
### Phase 4: Cleanup
|
||||
- [ ] Archive old prefabs (FlippableCard, AlbumCard)
|
||||
- [ ] Delete FlippableCard.cs
|
||||
- [ ] Delete AlbumCard.cs
|
||||
- [ ] Delete AlbumCardPlacementDraggable.cs (if fully replaced)
|
||||
- [ ] Run full regression test suite
|
||||
- [ ] Update team documentation
|
||||
- [ ] Celebrate! 🎉
|
||||
|
||||
---
|
||||
|
||||
## FAQ
|
||||
|
||||
**Q: Can I use both systems simultaneously?**
|
||||
A: Yes, during migration. One scene can use FlippableCard while another uses Card.prefab.
|
||||
|
||||
**Q: Will old prefabs still work?**
|
||||
A: Yes, until you delete the old scripts. Prefabs using FlippableCard will continue to function.
|
||||
|
||||
**Q: Do I need to migrate all at once?**
|
||||
A: No! Recommended approach is scene-by-scene (Phase 2, then Phase 3).
|
||||
|
||||
**Q: What about CardDisplay?**
|
||||
A: Keep it! It's used by both old and new systems. It's well-designed and doesn't need changes.
|
||||
|
||||
**Q: What if I find bugs in the new system?**
|
||||
A: Rollback to old system (see Rollback Plan section), fix bugs, then retry migration.
|
||||
|
||||
**Q: How long will migration take?**
|
||||
A: Estimated 6-10 hours total (2-4 for booster, 4-6 for album, testing time).
|
||||
|
||||
**Q: Will performance improve?**
|
||||
A: Yes! 60% less code, more efficient state management, shared animation system.
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
### Old Scripts Status:
|
||||
|
||||
| Script | Status | Timeline |
|
||||
|--------|--------|----------|
|
||||
| CardDisplay.cs | ✅ **KEEP** | Forever (it's perfect!) |
|
||||
| FlippableCard.cs | 🔄 **REPLACE** | Phase 2 (booster) |
|
||||
| AlbumCard.cs | 🔄 **REPLACE** | Phase 3 (album) |
|
||||
| AlbumCardPlacementDraggable.cs | 🔄 **REPLACE** | Phase 3 (album) |
|
||||
|
||||
### Migration Path:
|
||||
|
||||
```
|
||||
Now Phase 2 Phase 3 Future
|
||||
────────────────────────────────────────────────────────────
|
||||
Both systems → Booster uses → All use → Old scripts
|
||||
coexist new Card, new Card deleted
|
||||
album uses old
|
||||
```
|
||||
|
||||
### Key Insight:
|
||||
|
||||
**You're not "fixing" the old scripts - you're replacing their ARCHITECTURE.**
|
||||
|
||||
The old scripts work, but they're built on a flawed foundation (wrapper hell, boolean soup). The new system solves this with isolated states and clean separation of concerns.
|
||||
|
||||
Think of it like replacing a house's foundation - you keep the furniture (CardDisplay), but rebuild the structure underneath.
|
||||
|
||||
---
|
||||
|
||||
**Ready to start? Begin with Phase 2 (Booster Opening) - it's the cleanest migration path!**
|
||||
|
||||
Reference in New Issue
Block a user