14 KiB
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 byCard.cswith state machineAlbumCard.cs→ Replaced byCardPlacedInSlotState.cs+CardAlbumEnlargedState.csAlbumCardPlacementDraggable.cs→ Replaced byCard.cswithCardDraggingState.cs
Current Usage Analysis
Where FlippableCard is Used:
-
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
-
AlbumCardPlacementDraggable.cs (1 reference)
- Line 45: GetComponent reference
- Impact: Medium - album placement flow
-
AlbumCard.cs (1 reference)
- Line 94: GetComponentInParent during click forwarding
- Impact: Low - will be removed when AlbumCard is replaced
Where AlbumCard is Used:
-
AlbumCardSlot.cs (2 references)
- Line 186-187: Instantiate and GetComponent for pre-placed cards
- Impact: High - album slot system
-
AlbumViewPage.cs (2 references)
- Line 346: GetComponent when handling enlarge
- Line 457-458: Instantiate AlbumCardPlacementDraggable
- Impact: High - album view interactions
-
CardDisplay.cs (1 reference)
- Line 316: GetComponentInParent for preview mode
- Impact: Low - preview feature
-
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:
[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:
[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:
[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:
[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)
flippableCard.OnCardRevealed += (card, data) => { };
flippableCard.OnCardTappedAfterReveal += (card) => { };
flippableCard.OnFlipStarted += (card) => { };
flippableCard.OnClickedWhileInactive += (card) => { };
New Events (State-based)
// 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)
- Revert
BoosterOpeningPage.cschanges - Re-assign old
flippableCardPrefabin inspector - Old system still intact for album
During Phase 3 (Album Added)
- Revert
AlbumCardSlot.csandAlbumViewPage.cs - Re-assign old prefabs in inspector
- Both systems revert to old
After Phase 4 (Old Scripts Deleted)
- Restore old scripts from Git history
- Recreate old prefabs (if not archived)
- 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!