Code up the card part

This commit is contained in:
Michal Pikulski
2025-11-06 11:11:15 +01:00
parent b6d8586eab
commit 95daea8d34
24 changed files with 3179 additions and 4 deletions

View File

@@ -0,0 +1,365 @@
# Booster Opening System - Complete Setup Guide
## 📋 Overview
This guide walks you through setting up the complete booster opening flow, from the Album page to opening packs and revealing cards.
---
## 🎯 What Was Implemented
### **Core Components Enhanced:**
1. **DraggableSlot** - Added scale control for occupants
2. **BoosterPackDraggable** - Added tap-to-shake functionality
3. **BoosterPackVisual** - Added progressive shake animations
4. **BoosterOpeningPage** - Complete flow implementation
5. **AlbumViewPage** - Updated to pass booster count
### **Flow Summary:**
1. Album page shows booster buttons → Click → Opens BoosterOpeningPage
2. Opening page shows draggable boosters in bottom-right
3. Player taps or drags booster to center slot
4. Player taps booster X times (configurable, default 3)
5. Booster disappears, 3 card backs appear
6. Player clicks cards to reveal them one-by-one
7. After all revealed → Show next booster OR close page
---
## 🏗️ Scene Setup Instructions
### **Step 1: Create the BoosterOpeningPage GameObject**
1. **In your scene hierarchy:**
- Create an empty GameObject named `BoosterOpeningPage`
- Add component: `BoosterOpeningPage` script
- Add component: `Canvas Group` (for fade transitions)
- Ensure it's a child of your Canvas
2. **Create UI Structure:**
```
BoosterOpeningPage (BoosterOpeningPage component)
├── Background (Image - optional dark overlay)
├── CloseButton (Button)
├── BottomRightContainer (SlotContainer)
│ ├── Slot_0 (DraggableSlot)
│ ├── Slot_1 (DraggableSlot)
│ └── Slot_2 (DraggableSlot)
├── CenterSlot (DraggableSlot)
├── CardDisplayContainer (Empty RectTransform)
└── BoosterInstances (Empty container)
├── BoosterPack_0 (BoosterPackDraggable prefab)
├── BoosterPack_1 (BoosterPackDraggable prefab)
└── BoosterPack_2 (BoosterPackDraggable prefab)
```
---
## 📐 Detailed Component Setup
### **A. Bottom-Right Slot Container**
**GameObject Setup:**
- Name: `BottomRightContainer`
- Component: `SlotContainer`
- Position: Bottom-right of screen (e.g., anchored to bottom-right)
- Recommended position: X=800, Y=-400 (adjust for your canvas size)
**SlotContainer Settings:**
- Layout Type: `Vertical`
- Spacing: `120`
- Center Slots: ✓
- Auto Register Children: ✓
**Child Slots (Slot_0, Slot_1, Slot_2):**
- Add component: `DraggableSlot` to each
- Size: 150x200 (adjust to your booster size)
- Settings:
- Filter By Type: ✓
- Allowed Type Names: `BoosterPackDraggable`
- Apply Scale To Occupant: ☐ (leave normal size)
---
### **B. Center Opening Slot**
**GameObject Setup:**
- Name: `CenterSlot`
- Component: `DraggableSlot`
- Position: Center of screen (X=0, Y=0)
- Size: 300x400 (larger than boosters)
**DraggableSlot Settings:**
- Filter By Type: ✓
- Allowed Type Names: `BoosterPackDraggable`
- **Apply Scale To Occupant: ✓** ← Important!
- **Occupant Scale: (2, 2, 1)** ← Makes booster 2x bigger
- Scale Transition Duration: `0.3`
---
### **C. Card Display Container**
**GameObject Setup:**
- Name: `CardDisplayContainer`
- Component: `RectTransform` only
- Position: Center of screen (X=0, Y=-100)
- This is where revealed cards will spawn
---
### **D. Booster Pack Instances**
You have two options: **Prefabs** or **Scene Instances**
#### **Option 1: Using Prefabs (Recommended)**
1. **Create BoosterPack Prefab:**
```
BoosterPackPrefab
├── BoosterPackDraggable (component)
├── Image (base - raycastTarget = false)
└── Visual (BoosterPackVisual)
├── Canvas
├── CanvasGroup
├── TiltParent (Transform)
│ └── PackImage (Image - your booster sprite)
├── ShakeParent (Transform)
└── GlowEffect (ParticleSystem - optional)
```
2. **BoosterPackDraggable Settings:**
- Visual Prefab: Assign the Visual prefab
- Can Open On Drop: ☐
- Can Open On Double Click: ☐
- **Can Tap To Open: ✓**
- **Max Taps To Open: 3** (or your preference)
3. **In Scene:**
- Under `BoosterInstances` container, create 3 instances
- Name them: `BoosterPack_0`, `BoosterPack_1`, `BoosterPack_2`
- They will start inactive and be shown based on available count
#### **Option 2: Scene Instances**
- Place 3 booster GameObjects directly in the scene
- Configure as above
- Set initial Active state to `false`
---
### **E. Flippable Card Prefab**
**For now (placeholder):**
1. Create a simple prefab named `FlippableCardPrefab`
2. Structure:
```
FlippableCardPrefab
├── RectTransform (200x300)
├── CardDisplay (component)
├── Image (card back sprite initially)
└── Button (will be added at runtime if not present)
```
3. **Important:**
- The card should show a "back" sprite initially
- When clicked, `CardDisplay.SetupCard()` will be called
- In the future, add flip animation here
---
### **F. BoosterOpeningPage Component Configuration**
**In the Inspector:**
**UI References:**
- Canvas Group: Auto-assigned or drag the CanvasGroup
- Close Button: Drag your close button
**Booster Management:**
- Booster Pack Instances: **Array size = 3**
- Element 0: `BoosterPack_0`
- Element 1: `BoosterPack_1`
- Element 2: `BoosterPack_2`
- Bottom Right Slots: Drag `BottomRightContainer`
- Center Opening Slot: Drag `CenterSlot`
**Card Display:**
- Card Display Container: Drag `CardDisplayContainer`
- Flippable Card Prefab: Drag your card prefab
- Card Spacing: `150` (distance between cards)
**Settings:**
- Card Reveal Delay: `0.5`
- Booster Disappear Duration: `0.5`
---
## 🎨 Creating the Booster Pack Visual Prefab
### **Booster Visual Structure:**
```
BoosterVisual (BoosterPackVisual component)
├── Canvas (sort order will be controlled at runtime)
├── CanvasGroup (for fading)
├── TiltParent (empty Transform for 3D tilt effect)
│ ├── PackImage (Image - your booster pack sprite)
│ └── FrameImage (Image - optional frame/border)
├── ShakeParent (empty Transform for shake effects)
└── GlowEffect (Particle System - optional sparkles)
```
### **Component Settings:**
**BoosterPackVisual:**
- Canvas: Auto-assigned
- Canvas Group: Auto-assigned
- Tilt Parent: Drag `TiltParent`
- Shake Parent: Drag `ShakeParent`
- Pack Image: Drag the `PackImage`
- Pack Sprite: Assign your booster sprite asset
**Visual Animation Settings:**
- Follow Speed: `30`
- Rotation Amount: `20`
- Tilt Speed: `20`
- Use Idle Animation: ✓
- Idle Animation Speed: `1`
- Opening Scale Punch: `0.5`
- Opening Rotation Punch: `360`
- Opening Duration: `0.5`
---
## 🔗 Connecting to AlbumViewPage
**In your AlbumViewPage Inspector:**
- Booster Opening Page: Drag your `BoosterOpeningPage` GameObject
- Booster Pack Buttons: Array of booster button GameObjects (already configured)
**That's it!** The AlbumViewPage script already has the updated code to pass booster count.
---
## 🎮 Testing the Flow
### **Test Checklist:**
1. **Setup Test:**
- ✓ BoosterOpeningPage exists in scene
- ✓ All slots configured
- ✓ Booster instances assigned
- ✓ AlbumViewPage has reference to opening page
2. **Manual Booster Count:**
- In CardSystemManager, set initial booster count to 3
- Or use the editor tool to add boosters
3. **Test Flow:**
1. Open album → Should see 3 booster buttons
2. Click a booster button → Opens BoosterOpeningPage
3. Should see 3 boosters in bottom-right
4. **Drag Test:** Drag a booster to center → Should scale up 2x
5. **Tap Test:** Tap the booster 3 times:
- Tap 1: Small shake
- Tap 2: Medium shake
- Tap 3: Big shake → Booster disappears
6. Should see 3 card backs appear
7. Click each card → Should reveal (show CardDisplay)
8. After all revealed → Should show next booster OR close page
---
## ⚙️ Configuration Options
### **Adjusting Tap Count:**
- Select any BoosterPackDraggable
- Change `Max Taps To Open` (3 is default)
### **Adjusting Booster Cap:**
- In BoosterOpeningPage, change `Booster Pack Instances` array size
- Add/remove booster instances
- Bottom-right slots should match (add more Slot children)
### **Adjusting Center Slot Scale:**
- Select `CenterSlot`
- Change `Occupant Scale` (2,2,1 = 2x size)
### **Card Spacing:**
- In BoosterOpeningPage, adjust `Card Spacing` (150 default)
---
## 🐛 Troubleshooting
### **Problem: Boosters don't appear**
- Check: `Booster Pack Instances` array is filled
- Check: CardSystemManager has boosters available
- Check: AlbumViewPage passes booster count correctly
### **Problem: Can't drag booster to center**
- Check: CenterSlot has `Filter By Type` with `BoosterPackDraggable`
- Check: CenterSlot is not locked initially
- Check: Booster has Image with `raycastTarget = true` on base object
### **Problem: Tapping doesn't work**
- Check: BoosterPackDraggable has `Can Tap To Open` enabled
- Check: Booster is in the center slot (tap only works when slotted)
- Check: Visual children have `raycastTarget = false` so taps reach the base
### **Problem: Booster doesn't scale up in center**
- Check: CenterSlot has `Apply Scale To Occupant` enabled
- Check: `Occupant Scale` is set (e.g., 2,2,1)
### **Problem: Cards don't reveal**
- Check: `Flippable Card Prefab` is assigned
- Check: Prefab has CardDisplay component
- Check: CardDisplay can receive card data
---
## 🎨 Visual Polish (Optional Next Steps)
### **Enhance Card Flip:**
- Add rotation animation when revealing
- Use DOTween or Tween for 3D flip effect
- Particle effects on reveal
### **Booster Opening Effects:**
- More dramatic particles when opening
- Sound effects on taps and opening
- Screen shake on final tap
### **Transition Polish:**
- Boosters fly in on page open
- Cards fly out after revealing
- Smooth transitions between boosters
---
## 📝 Summary
**You now have:**
✅ Complete booster opening flow
✅ Tap-to-shake interaction (3 taps default)
✅ Drag-and-drop alternative
✅ Card reveal system (click to flip)
✅ Auto-progression to next booster
✅ Auto-close when no boosters left
✅ Scalable system (adjust array size for more boosters)
**Next Steps:**
1. Create your visual assets (booster sprites, card backs)
2. Set up the scene structure as outlined
3. Configure the BoosterOpeningPage component
4. Test the flow
5. Polish with animations and effects
**Need Help?**
- Reference the existing drag-and-drop documentation
- Check CardSystem documentation for card data structure
- Test individual components in isolation first
---
🎉 **Happy Booster Opening!** 🎉

View File

@@ -0,0 +1,342 @@
# Booster Pack Prefab Structure Guide
## 🎨 Complete Booster Pack Prefab Setup
This guide shows you exactly how to structure your booster pack prefabs for the opening system.
---
## 📦 BoosterPackDraggable Prefab Structure
```
BoosterPackPrefab (RectTransform)
├── [Components on Root]
│ ├── RectTransform (200x300 size recommended)
│ ├── Image (IMPORTANT: raycastTarget = TRUE - for clicking/dragging)
│ ├── BoosterPackDraggable (script)
│ └── Canvas Group (optional - for fading)
└── Visual (Child GameObject)
└── [BoosterPackVisual Prefab Instance]
```
---
## 🎭 BoosterPackVisual Prefab Structure
```
BoosterVisual (RectTransform)
├── [Components on Root]
│ ├── RectTransform (same size as parent)
│ ├── Canvas (will be controlled at runtime)
│ ├── CanvasGroup (for alpha transitions)
│ └── BoosterPackVisual (script)
├── TiltParent (Empty Transform)
│ │ [This rotates for 3D tilt effect]
│ │
│ ├── PackImage (Image)
│ │ ├── Sprite: Your booster pack sprite
│ │ ├── raycastTarget: FALSE
│ │ └── Size: Slightly smaller than parent
│ │
│ ├── FrameImage (Image - optional)
│ │ ├── Sprite: Border/frame decoration
│ │ └── raycastTarget: FALSE
│ │
│ └── RarityIndicator (Image - optional)
│ ├── Sprite: Rarity gem/star
│ └── raycastTarget: FALSE
├── ShakeParent (Empty Transform)
│ │ [This is used for shake offset]
│ └── (Currently empty, reserved for effects)
└── GlowEffect (Particle System - optional)
├── Shape: Circle
├── Start Size: 5-10
├── Start Color: Golden/sparkly
├── Emission Rate: 10-20
└── Renderer: Sort Order = 1 (above images)
```
---
## ⚙️ Component Configuration
### **BoosterPackDraggable Settings:**
```yaml
[Draggable Settings]
Move Speed: 50
Smooth Movement:
Snap Duration: 0.3
[Visual]
Visual Prefab: (Assign BoosterVisual prefab)
Instantiate Visual:
Visual Parent: (Leave empty - uses canvas)
[Selection]
Is Selectable:
Selection Offset: 50
[Booster Pack Settings]
Can Open On Drop:
Can Open On Double Click:
[Tap to Open]
Can Tap To Open:
Max Taps To Open: 3
```
### **BoosterPackVisual Settings:**
```yaml
[References]
Canvas: (Auto-assigned)
Canvas Group: (Auto-assigned)
Tilt Parent: (Drag TiltParent object)
Shake Parent: (Drag ShakeParent object)
[Follow Parameters]
Follow Speed: 30
Use Follow Delay:
[Rotation/Tilt Parameters]
Rotation Amount: 20
Rotation Speed: 20
Auto Tilt Amount: 30
Manual Tilt Amount: 20
Tilt Speed: 20
[Scale Parameters]
Use Scale Animations:
Scale On Hover: 1.15
Scale On Drag: 1.25
Scale Transition Duration: 0.15
[Idle Animation]
Use Idle Animation:
Idle Animation Speed: 1
[Booster Pack Visual]
Pack Image: (Drag PackImage)
Pack Sprite: (Assign your sprite asset)
Glow Effect: (Drag particle system if using)
Glow Transform: (Drag particle transform if using)
[Opening Animation]
Opening Scale Punch: 0.5
Opening Rotation Punch: 360
Opening Duration: 0.5
```
---
## 🎨 Creating in Unity (Step-by-Step)
### **Step 1: Create Root GameObject**
1. Right-click in Hierarchy → UI → Image
2. Name it: `BoosterPackPrefab`
3. Set Size: 200x300 (Width x Height)
4. Add sprite: Temporary placeholder or your booster sprite
5. **IMPORTANT:** Ensure `raycastTarget` is ✓ checked
### **Step 2: Add BoosterPackDraggable**
1. Add Component → `BoosterPackDraggable`
2. Configure settings (see above)
3. Leave Visual Prefab empty for now
### **Step 3: Create Visual Child**
1. Right-click BoosterPackPrefab → Create Empty
2. Name it: `BoosterVisual`
3. Add Component → `Canvas`
4. Add Component → `Canvas Group`
5. Add Component → `BoosterPackVisual`
### **Step 4: Create TiltParent**
1. Right-click BoosterVisual → Create Empty
2. Name it: `TiltParent`
3. Position: (0, 0, 0)
### **Step 5: Add Images under TiltParent**
1. Right-click TiltParent → UI → Image
2. Name it: `PackImage`
3. Assign your booster sprite
4. **Set raycastTarget to ☐ UNCHECKED**
5. Size: 180x280 (slightly smaller)
### **Step 6: Create ShakeParent**
1. Right-click BoosterVisual → Create Empty
2. Name it: `ShakeParent`
3. Position: (0, 0, 0)
### **Step 7: Add Glow Effect (Optional)**
1. Right-click BoosterVisual → Effects → Particle System
2. Name it: `GlowEffect`
3. Configure:
- Duration: 1
- Looping: ✓
- Start Lifetime: 1-2
- Start Speed: 0
- Start Size: 5-10
- Start Color: Gold/Yellow with alpha
- Shape: Circle, Radius: 1
- Emission: Rate over Time = 15
- Renderer: Material = Default Particle, Sort Order = 1
### **Step 8: Wire Up References**
1. Select `BoosterVisual`
2. In BoosterPackVisual component:
- Tilt Parent: Drag `TiltParent`
- Shake Parent: Drag `ShakeParent`
- Pack Image: Drag `PackImage`
- Pack Sprite: Assign sprite asset
- Glow Effect: Drag `GlowEffect` (if using)
### **Step 9: Make Prefab**
1. Drag `BoosterPackPrefab` to Project folder
2. Delete from scene
3. You now have a reusable prefab!
---
## 🎯 Instantiation in Scene
### **Option A: Prefab Instances (Recommended)**
In your BoosterOpeningPage scene:
1. Create empty GameObject: `BoosterInstances`
2. Drag 3 instances of your prefab into it
3. Name them: `BoosterPack_0`, `BoosterPack_1`, `BoosterPack_2`
4. Set all to Active = ☐ (unchecked)
5. Position doesn't matter - they'll be assigned to slots
### **Option B: Runtime Instantiation**
- Assign the prefab to BoosterOpeningPage
- Script will instantiate as needed
- (Not implemented yet, but easy to add)
---
## 🧪 Testing Your Prefab
### **Test 1: Visual Check**
1. Place one instance in scene (active)
2. Enter Play Mode
3. Should see: Sprite, idle wobble animation
4. Hover over it: Should scale up slightly
### **Test 2: Drag Test**
1. Create a SlotContainer with a slot
2. Try dragging the booster to the slot
3. Should snap smoothly
4. Visual should lerp-follow with delay
### **Test 3: Tap Test**
1. Place booster in a slot
2. Set Can Tap To Open = ✓, Max Taps = 3
3. Click 3 times
4. Should see increasing shakes
---
## 📐 Size Recommendations
### **For Mobile:**
- Booster: 200x300
- Center Slot Scale: 2x → 400x600
- Card: 180x250
### **For Desktop:**
- Booster: 250x350
- Center Slot Scale: 1.5x → 375x525
- Card: 200x280
### **Spacing:**
- Bottom slots: 120-150 units apart
- Cards: 150-200 units apart
---
## 🎨 Sprite Requirements
### **Booster Pack Sprite:**
- Recommended: 512x768 or 1024x1536
- Format: PNG with transparency
- Style: Vertical rectangle (2:3 ratio)
- Should have clear visual identity
### **Card Back Sprite:**
- Same aspect ratio as cards
- Clearly distinct from front
- Can match booster theme
---
## 🔧 Troubleshooting Prefabs
**Problem: Can't click/drag booster**
→ Check: Root Image has raycastTarget = ✓
→ Check: Visual children have raycastTarget = ☐
**Problem: Visual doesn't follow smoothly**
→ Check: BoosterPackVisual is initialized
→ Check: Follow Speed > 0, Use Follow Delay = ✓
**Problem: No shake animation**
→ Check: BoosterPackVisual subscribes to OnTapped
→ Check: TiltParent and ShakeParent are assigned
**Problem: Booster looks weird when dragging**
→ Check: TiltParent contains the images
→ Check: Rotation parameters are reasonable (10-30)
---
## 💡 Advanced Customization
### **Rarity-Based Visuals:**
Add different sprites or effects based on rarity:
```csharp
// In BoosterPackDraggable or Visual:
public enum BoosterRarity { Common, Rare, Legendary }
public BoosterRarity rarity;
// Change sprite/effects based on rarity
```
### **Opening Sequence:**
Customize the opening animation:
- Adjust Opening Scale Punch (0.5 default)
- Adjust Opening Rotation Punch (360 default)
- Add sound effects in `PlayOpeningAnimation()`
### **Hover Effects:**
Make boosters more responsive:
- Increase Scale On Hover (1.15 → 1.3)
- Add glow intensity on hover
- Tilt toward mouse more (Manual Tilt Amount)
---
## ✅ Final Checklist
Before using your prefab:
- [ ] Root has BoosterPackDraggable
- [ ] Root Image has raycastTarget = TRUE
- [ ] Visual child has BoosterPackVisual
- [ ] TiltParent exists and contains sprites
- [ ] ShakeParent exists
- [ ] All image children have raycastTarget = FALSE
- [ ] References are wired up in Visual
- [ ] Prefab is saved in Project
- [ ] Can Tap To Open = ✓
- [ ] Max Taps To Open = 3 (or your choice)
---
🎉 **You're ready to create beautiful, interactive booster packs!** 🎉

View File

@@ -0,0 +1,309 @@
# Drag and Drop Card System
A robust, touch-compatible drag-and-drop system for Unity UI, inspired by Balatro's visual feel. Supports cards, booster packs, and any other draggable objects with smooth visual effects.
## Architecture Overview
The system is built on a separation of concerns:
- **Logic Layer** (`DraggableObject`) - Handles dragging, slot snapping, events
- **Visual Layer** (`DraggableVisual`) - Follows the logic object with lerping, tilting, animations
- **Slot System** (`DraggableSlot` + `SlotContainer`) - Manages positions and layout
## Core Components
### 1. DraggableObject (Abstract Base Class)
Base class for any draggable UI element.
**Key Features:**
- Touch-compatible via Unity's pointer event system
- Smooth movement toward pointer (configurable)
- Automatic slot snapping on release
- Selection support with visual offset
- Comprehensive event system
**Usage:**
```csharp
public class MyDraggable : DraggableObject
{
protected override void OnDragStartedHook()
{
// Custom logic when drag starts
}
}
```
### 2. DraggableVisual (Abstract Base Class)
Visual representation that follows the DraggableObject.
**Key Features:**
- Lerps toward parent position (not instant)
- Tilt based on movement velocity
- Auto-tilt idle animation (sine/cosine wobble)
- Manual tilt when hovering
- Scale animations on hover/drag/select
**Usage:**
```csharp
public class MyVisual : DraggableVisual
{
protected override void UpdateVisualContent()
{
// Update your visual elements here
}
}
```
### 3. DraggableSlot
Represents a position where draggables can snap.
**Key Features:**
- Occupancy management (one object per slot)
- Type filtering (restrict which types can occupy)
- Lock/unlock functionality
- Swap support
### 4. SlotContainer
Manages a collection of slots.
**Key Features:**
- Multiple layout types (Horizontal, Vertical, Grid, Custom)
- Curve-based positioning for horizontal layouts
- Automatic slot registration
- Find closest slot algorithm
**Layout Types:**
- **Horizontal** - Slots arranged in a horizontal line (with optional curve)
- **Vertical** - Slots arranged in a vertical line
- **Grid** - Slots arranged in a grid pattern
- **Custom** - Manually position slots
## Card-Specific Implementations
### CardDraggable
Card-specific draggable implementation.
**Features:**
- Holds `CardData` reference
- Events for card data changes
- Integrates with `CardSystemManager`
**Example:**
```csharp
CardDraggable card = GetComponent<CardDraggable>();
card.SetCardData(myCardData);
```
### CardDraggableVisual
Visual representation for cards.
**Features:**
- Uses existing `CardDisplay` component
- Shadow effects on press
- Automatic visual refresh when card data changes
### BoosterPackDraggable
Booster pack implementation.
**Features:**
- Double-click to open support
- Opening state management
- Events for opening
### BoosterPackVisual
Visual representation for booster packs.
**Features:**
- Glow particle effects
- Opening animation (scale + rotation)
- Sprite customization
## Setup Guide
### Basic Setup
1. **Create Slot Container:**
```
GameObject → UI → Panel (rename to "CardSlotContainer")
Add Component → SlotContainer
```
2. **Create Slots:**
```
Under CardSlotContainer:
GameObject → UI → Empty (rename to "Slot_01")
Add Component → DraggableSlot
```
Duplicate for as many slots as needed.
3. **Create Draggable Card:**
```
GameObject → UI → Image (rename to "CardDraggable")
Add Component → CardDraggable
```
4. **Create Visual Prefab:**
```
Create a prefab with:
- Root: Empty GameObject with CardDraggableVisual component
- Child: Canvas (for sorting control)
- Child: TiltParent (Transform for tilt effects)
- Child: ShakeParent (Transform for punch effects)
- Child: CardDisplay (your existing card visual)
```
5. **Link Visual to Draggable:**
```
On CardDraggable:
- Assign your visual prefab to "Visual Prefab"
- Set "Instantiate Visual" to true
```
### Advanced: Curved Hand Layout
For a Balatro-style curved card hand:
1. On SlotContainer:
- Set Layout Type to "Horizontal"
- Enable "Use Curve Layout"
- Edit "Position Curve" (try: keys at 0,0.5,1 with values 0,1,0)
- Set "Curve Height" (e.g., 50)
- Enable "Center Slots"
2. Adjust spacing to fit your card size
## Event System
### DraggableObject Events:
```csharp
draggable.OnDragStarted += (obj) => { };
draggable.OnDragEnded += (obj) => { };
draggable.OnPointerEntered += (obj) => { };
draggable.OnPointerExited += (obj) => { };
draggable.OnPointerDowned += (obj) => { };
draggable.OnPointerUpped += (obj, longPress) => { };
draggable.OnSelected += (obj, selected) => { };
draggable.OnSlotChanged += (obj, slot) => { };
```
### CardDraggable Events:
```csharp
cardDraggable.OnCardDataChanged += (card, data) => { };
```
### BoosterPackDraggable Events:
```csharp
boosterDraggable.OnBoosterOpened += (pack) => { };
```
## Touch Support
The system is fully touch-compatible out of the box! Unity's Event System automatically routes touch events through the pointer interfaces.
**Supported Gestures:**
- Single touch drag
- Tap to select
- Double-tap (on booster packs)
- Long press detection
**Note:** For multi-touch support, the system uses PointerEventData which handles the first touch automatically. Additional touch support can be added by extending the pointer event handlers.
## Performance Tips
1. **Disable Idle Animations** if you have many cards:
```
On DraggableVisual: useIdleAnimation = false
```
2. **Reduce Follow Speed** for smoother performance:
```
On DraggableVisual: followSpeed = 20 (default: 30)
```
3. **Disable Scale Animations** if needed:
```
On DraggableVisual: useScaleAnimations = false
```
4. **Use Object Pooling** for spawning many cards
## Extending the System
### Creating Custom Draggable Types
1. Inherit from `DraggableObject`:
```csharp
public class MyCustomDraggable : DraggableObject
{
protected override void OnDragStartedHook()
{
// Your logic
}
}
```
2. Inherit from `DraggableVisual`:
```csharp
public class MyCustomVisual : DraggableVisual
{
protected override void UpdateVisualContent()
{
// Update your visuals
}
}
```
### Custom Slot Filtering
```csharp
// On DraggableSlot component:
filterByType = true
allowedTypeNames = { "CardDraggable", "BoosterPackDraggable" }
```
## Troubleshooting
**Cards don't snap to slots:**
- Ensure SlotContainer has slots registered
- Check that slots aren't locked
- Verify type filtering isn't blocking the card
**Visuals don't follow smoothly:**
- Check followSpeed value (try 20-40)
- Ensure TiltParent and ShakeParent are assigned
- Verify the visual prefab has correct hierarchy
**Touch not working:**
- Ensure EventSystem exists in scene
- Check Canvas Raycast Target is enabled
- Verify GraphicRaycaster is on Canvas
**Cards jitter or shake:**
- Reduce followSpeed
- Disable idle animation
- Check for conflicting tweens
## Integration with Card System
The drag-and-drop system integrates seamlessly with your existing `CardSystemManager`:
```csharp
// Spawn a draggable card from CardData
CardData cardData = CardSystemManager.Instance.GetAllCollectedCards()[0];
GameObject cardObj = Instantiate(cardDraggablePrefab, slotContainer.transform);
CardDraggable card = cardObj.GetComponent<CardDraggable>();
card.SetCardData(cardData);
// Assign to first available slot
DraggableSlot slot = slotContainer.GetAvailableSlots().FirstOrDefault();
if (slot != null)
{
card.AssignToSlot(slot, false);
}
```
## Credits
Inspired by the excellent feel of Balatro's card system (mixandjam/balatro-feel on GitHub).
Adapted for AppleHills card collection game with full touch support and Unity UI integration.