# Hockey Faceoff System Documentation ## Overview A complete faceoff and puck possession system for your hockey game with realistic physics, visual indicators, and AI-ready mechanics. --- ## 📦 Components Created ### 1. **PuckController.cs** Controls the puck physics and possession mechanics. **Features:** - Realistic hockey puck physics (170g mass, low friction) - Automatic possession detection via trigger colliders - Visual feedback (different materials for possessed/free states) - Smooth carrying while player has possession - Physics-based shooting and passing **Key Properties:** - `possessionRadius`: Distance within which players can pick up the puck (default: 1.5m) - `carrierOffset`: How far in front of player the puck stays when carried (default: 1.0m) ### 2. **FaceoffManager.cs** Manages the entire faceoff sequence and outcome determination. **Faceoff Outcomes:** - **Home Win**: Home center wins cleanly, puck passed to teammate (usually defender) - **Away Win**: Away center wins cleanly, puck passed to teammate (usually defender) - **Struggle**: Close contest, puck bounces loose, scramble ensues **How Outcomes Are Determined:** ``` Faceoff Strength = (Strength × 0.3) + (Stick Handling × 0.3) + (Awareness × 0.2) + (Agility × 0.2) ``` Plus random variation (±10 points) for unpredictability. **Testing:** Press **F** key during play mode to trigger a faceoff. ### 3. **PlayerController.cs** (Updated) Enhanced with puck interaction methods. **New Methods:** - `GainPuck(PuckController)`: Called when player gains possession - `ReleasePuck()`: Called when player loses possession - `CanPickupPuck()`: Checks if player can currently pick up puck - `SetFrozen(bool)`: Freeze/unfreeze player during faceoff - `Shoot(direction, power)`: Fire the puck with physics - `Pass(targetPlayer)`: Pass to specific teammate - `Check(targetPlayer)`: Body check opponent to dislodge puck **Visual Feedback:** - Yellow rotating ring appears around player with possession - Makes it instantly clear who controls the puck --- ## 🎮 Setup Instructions ### Method 1: Manual Setup 1. **Create the Puck:** ``` - Create GameObject → name it "Puck" - Add PuckController component - Position at center ice (y ≈ 0.5 for ice level) ``` 2. **Tag Your Players:** ``` - Edit → Project Settings → Tags & Layers - Add tags: "HomeTeam" and "AwayTeam" - Select home team players → Inspector → Tag: "HomeTeam" - Select away team players → Inspector → Tag: "AwayTeam" ``` 3. **Create Faceoff Manager:** ``` - Create Empty GameObject → name it "FaceoffManager" - Add FaceoffManager component - Drag Puck into the "Puck" field in Inspector ``` 4. **Verify Centers:** - Ensure one player on each team has Position = "C" (Center) - The FaceoffManager auto-detects centers by tag and position ### Method 2: Auto Setup (Recommended) 1. Create an empty GameObject 2. Add `FaceoffSetupGuide` component 3. Drag home team players into "Home Team Players" array 4. Drag away team players into "Away Team Players" array 5. Right-click component → "Auto-Setup Faceoff System" 6. Right-click component → "Validate Setup" to check everything --- ## 🏒 How It Works ### Possession System **Puck States:** - **Loose**: No one has possession, slides freely on ice - **Carried**: Attached to a player, moves with them **Gaining Possession:** Player automatically picks up puck when: 1. Player is within `possessionRadius` (1.5m) 2. Puck is loose (not carried by anyone) 3. Player can pickup (not on cooldown, not frozen) 4. Puck enters player's trigger collider **Visual Indicator:** - Yellow ring with emission around player = has puck - Ring rotates continuously for visibility ### Faceoff Sequence ``` 1. FaceoffManager.StartFaceoff() called ↓ 2. Puck positioned at faceoff spot ↓ 3. All players frozen (prevent movement) ↓ 4. Calculate outcome based on center stats ↓ 5. Execute outcome: - Clean Win: Puck passed to defender - Struggle: Puck bounces loose ↓ 6. Unfreeze all players ↓ 7. Game continues ``` **Timing:** - Wind-up: 1 second - Faceoff duration: 2 seconds - Struggle duration: 3 additional seconds ### Physics Details **Puck Properties:** - Mass: 0.17 kg (170g, regulation weight) - Radius: 0.038m (76mm diameter) - Friction: 0.3 (simulates ice) - Bounciness: 0.2 (minimal bounce) **Force Ranges:** - Pass: 10-25 N (scales with distance) - Shot: ~30 N × power stat - Faceoff launch: 5-15 N --- ## 🎯 Integration Examples ### Example 1: Start Faceoff at Game Start ```csharp public class GameManager : MonoBehaviour { private FaceoffManager faceoffManager; void Start() { faceoffManager = FindObjectOfType(); // Start game with center ice faceoff Vector3 centerIce = new Vector3(0, 0.5f, 0); faceoffManager.InitiateFaceoff(centerIce); } } ``` ### Example 2: Player Shoots on Goal ```csharp public class PlayerAI : MonoBehaviour { private PlayerController playerController; private Transform goal; void ShootAtGoal() { if (playerController.HasPuck()) { Vector3 shootDirection = (goal.position - transform.position).normalized; playerController.Shoot(shootDirection, powerMultiplier: 1.0f); } } } ``` ### Example 3: Pass to Open Teammate ```csharp public void PassToOpenPlayer() { if (!playerController.HasPuck()) return; PlayerController[] teammates = FindTeammates(); PlayerController bestTarget = FindMostOpen(teammates); if (bestTarget != null) { playerController.Pass(bestTarget); } } ``` ### Example 4: Defensive Check ```csharp void OnCollisionEnter(Collision collision) { PlayerController opponent = collision.gameObject.GetComponent(); if (opponent != null && opponent.HasPuck() && IsOpponent(opponent)) { playerController.Check(opponent); } } ``` --- ## 🔧 Customization ### Adjust Faceoff Difficulty In `FaceoffManager.cs`: ```csharp [SerializeField] private float struggleChance = 0.3f; // 30% base struggle chance [SerializeField] private float winThreshold = 0.7f; // Higher = more clear wins needed ``` ### Change Puck Physics In `PuckController.cs`: ```csharp [SerializeField] private float friction = 0.3f; // Lower = slides further [SerializeField] private float drag = 0.5f; // Higher = stops faster ``` ### Modify Possession Range In `PuckController.cs`: ```csharp [SerializeField] private float possessionRadius = 1.5f; // Detection range ``` --- ## 🐛 Troubleshooting ### Puck doesn't get picked up - Check that player has trigger collider - Verify `CanPickupPuck()` returns true - Check pickup cooldown hasn't expired ### Faceoff doesn't start - Verify both centers are tagged correctly - Check console for error messages - Run "Validate Setup" in FaceoffSetupGuide ### Players don't freeze during faceoff - Ensure PlayerController has `SetFrozen()` method - Check that player movement script respects frozen state ### Possession indicator doesn't show - Verify possessionIndicator GameObject is created in PlayerController.Start() - Check that Update() is being called --- ## 📊 Stats That Matter ### For Faceoffs: - **Strength** (30%): Physical dominance - **Stick Handling** (30%): Puck control - **Awareness** (20%): Reading the drop - **Agility** (20%): Quick reactions ### For Shooting: - **Shot Accuracy**: Determines spread angle - **Shot Power**: Determines puck velocity ### For Passing: - **Pass Accuracy**: Determines pass precision ### For Checking: - **Checking**: Success rate of dislodging puck --- ## 🎨 Visual Enhancements (Optional) ### Add Trail to Puck: ```csharp TrailRenderer trail = puck.gameObject.AddComponent(); trail.time = 0.5f; trail.startWidth = 0.1f; trail.endWidth = 0.02f; ``` ### Add Particles When Puck is Hit: ```csharp // In PuckController.OnCollisionEnter() ParticleSystem.Emit(5); // Ice spray effect ``` ### Change Possession Ring Color by Team: ```csharp if (CompareTag("HomeTeam")) possessionIndicator.GetComponent().material.color = Color.blue; else possessionIndicator.GetComponent().material.color = Color.red; ``` --- ## 🚀 Next Steps 1. **Add Goalie**: Extend PlayerController for goalie-specific behavior 2. **Implement Offsides**: Check puck/player positions 3. **Add Icing**: Detect long-range clears 4. **Improve AI**: Use puck position in decision-making 5. **Add Penalties**: Faceoff after penalty ends 6. **Post-Goal Faceoffs**: Return to center after scoring --- ## Summary You now have: ✅ Physics-based puck with realistic ice behavior ✅ Clear visual indication of possession (yellow ring) ✅ Faceoff system with 3 outcomes based on player stats ✅ Ready-to-use shooting, passing, and checking mechanics ✅ Easy integration with your existing player system **Test it:** Press **F** in play mode to see a faceoff in action!