464 lines
14 KiB
Markdown
464 lines
14 KiB
Markdown
|
|
# 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!**
|
||
|
|
|