Parcourir la source

Faceoff working

Axel Nordh il y a 3 mois
Parent
commit
a1929dca08

+ 3 - 0
Assembly-CSharp.csproj

@@ -53,11 +53,13 @@
     <Compile Include="Assets\Scripts\GameFlowExample.cs" />
     <Compile Include="Assets\Scripts\FaceoffSetupGuide.cs" />
     <Compile Include="Assets\Scripts\Player\AI\AIStrategy.cs" />
+    <Compile Include="Assets\Scripts\FaceoffDebugVisualizer.cs" />
     <Compile Include="Assets\Scripts\Player\PlayerInput.cs" />
     <Compile Include="Assets\Scripts\Player\PlayerMovement.cs" />
     <Compile Include="Assets\Scripts\Player\PlayerController.cs" />
     <Compile Include="Assets\Scripts\FaceoffPositioning.cs" />
     <Compile Include="Assets\Scripts\FaceoffManager.cs" />
+    <Compile Include="Assets\Scripts\GameSetup.cs" />
     <Compile Include="Assets\Scripts\Player\AI\PlayerMentality.cs" />
     <Compile Include="Assets\Scripts\Player\PlayerStats.cs" />
     <Compile Include="Assets\Scripts\Player\AI\OffensiveStrategy.cs" />
@@ -66,6 +68,7 @@
     <Compile Include="Assets\Scripts\Player\PlayerAnimationController.cs" />
     <Compile Include="Assets\Scripts\Player\AI\DefensiveStrategy.cs" />
     <Compile Include="Assets\Scripts\Player\AI\PlayerDecisionMaker.cs" />
+    <Compile Include="Assets\Scripts\LayerAssigner.cs" />
   </ItemGroup>
   <ItemGroup>
     <None Include="Assets\TextMesh Pro\Shaders\TMPro.cginc" />

+ 41 - 29
Assets/Scenes/SampleScene.unity

@@ -771,7 +771,7 @@ PrefabInstance:
       objectReference: {fileID: 0}
     - target: {fileID: -8679921383154817045, guid: 6145e593b01004c468111c01c6063c84, type: 3}
       propertyPath: m_LocalPosition.y
-      value: 0.138
+      value: 0
       objectReference: {fileID: 0}
     - target: {fileID: -8679921383154817045, guid: 6145e593b01004c468111c01c6063c84, type: 3}
       propertyPath: m_LocalPosition.z
@@ -1155,6 +1155,7 @@ GameObject:
   m_Component:
   - component: {fileID: 1453121554}
   - component: {fileID: 1453121553}
+  - component: {fileID: 1453121555}
   m_Layer: 0
   m_Name: FaceoffManager
   m_TagString: Untagged
@@ -1188,9 +1189,8 @@ MonoBehaviour:
   struggleDuration: 3
   struggleChance: 0.3
   winThreshold: 0.7
-  minLaunchForce: 5
-  maxLaunchForce: 15
-  upwardForce: 0.5
+  passForce: 8
+  struggleLaunchForce: 5
 --- !u!4 &1453121554
 Transform:
   m_ObjectHideFlags: 0
@@ -1206,6 +1206,20 @@ Transform:
   m_Children: []
   m_Father: {fileID: 0}
   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!114 &1453121555
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1453121552}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 4dafffd55a342ad4f82abc92f32ee813, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: Assembly-CSharp::FaceoffSpotHelper
+  gizmoColor: {r: 1, g: 0, b: 0, a: 1}
+  circleRadius: 1
 --- !u!1001 &1555471120
 PrefabInstance:
   m_ObjectHideFlags: 0
@@ -1382,9 +1396,9 @@ GameObject:
   - component: {fileID: 2015482868}
   - component: {fileID: 2015482867}
   - component: {fileID: 2015482866}
-  - component: {fileID: 2015482865}
   - component: {fileID: 2015482864}
   - component: {fileID: 2015482869}
+  - component: {fileID: 2015482870}
   m_Layer: 0
   m_Name: Puck
   m_TagString: Untagged
@@ -1419,29 +1433,6 @@ Rigidbody:
   m_Interpolate: 0
   m_Constraints: 0
   m_CollisionDetection: 1
---- !u!136 &2015482865
-CapsuleCollider:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_GameObject: {fileID: 2015482863}
-  m_Material: {fileID: 13400000, guid: ef9e017bed615f744952902cf910d8ac, type: 2}
-  m_IncludeLayers:
-    serializedVersion: 2
-    m_Bits: 0
-  m_ExcludeLayers:
-    serializedVersion: 2
-    m_Bits: 0
-  m_LayerOverridePriority: 0
-  m_IsTrigger: 0
-  m_ProvidesContacts: 0
-  m_Enabled: 1
-  serializedVersion: 2
-  m_Radius: 0.5000001
-  m_Height: 2
-  m_Direction: 1
-  m_Center: {x: 0.000000059604645, y: 0, z: -0.00000008940697}
 --- !u!23 &2015482866
 MeshRenderer:
   m_ObjectHideFlags: 0
@@ -1507,7 +1498,7 @@ Transform:
   m_GameObject: {fileID: 2015482863}
   serializedVersion: 2
   m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
-  m_LocalPosition: {x: 0, y: 0.182, z: 0}
+  m_LocalPosition: {x: 0, y: 0.25, z: 0}
   m_LocalScale: {x: 0.15, y: 0.03, z: 0.15}
   m_ConstrainProportionsScale: 0
   m_Children:
@@ -1534,6 +1525,27 @@ MonoBehaviour:
   carrierOffset: 1
   normalMaterial: {fileID: 0}
   possessedMaterial: {fileID: 0}
+--- !u!135 &2015482870
+SphereCollider:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2015482863}
+  m_Material: {fileID: 13400000, guid: ef9e017bed615f744952902cf910d8ac, type: 2}
+  m_IncludeLayers:
+    serializedVersion: 2
+    m_Bits: 0
+  m_ExcludeLayers:
+    serializedVersion: 2
+    m_Bits: 0
+  m_LayerOverridePriority: 0
+  m_IsTrigger: 0
+  m_ProvidesContacts: 0
+  m_Enabled: 1
+  serializedVersion: 3
+  m_Radius: 0.38
+  m_Center: {x: 0.00000005960464, y: 0, z: -0.00000008940696}
 --- !u!1001 &2034510359
 PrefabInstance:
   m_ObjectHideFlags: 0

+ 43 - 0
Assets/Scripts/FaceoffDebugVisualizer.cs

@@ -0,0 +1,43 @@
+using UnityEngine;
+
+public class FaceoffDebugVisualizer : MonoBehaviour
+{
+    [SerializeField] private FaceoffManager faceoffManager;
+    [SerializeField] private bool showDebug = true;
+
+    private Vector3 lastPassStart;
+    private Vector3 lastPassEnd;
+    private float debugTimer = 0f;
+
+    void Update()
+    {
+        if (debugTimer > 0)
+        {
+            debugTimer -= Time.deltaTime;
+        }
+    }
+
+    void OnDrawGizmos()
+    {
+        if (!showDebug || debugTimer <= 0) return;
+
+        // Draw pass line
+        Gizmos.color = Color.cyan;
+        Gizmos.DrawLine(lastPassStart, lastPassEnd);
+        Gizmos.DrawSphere(lastPassStart, 0.2f);
+        Gizmos.DrawSphere(lastPassEnd, 0.2f);
+
+        // Draw arrow
+        Vector3 direction = (lastPassEnd - lastPassStart).normalized;
+        Vector3 arrowPoint = lastPassStart + direction * Vector3.Distance(lastPassStart, lastPassEnd) * 0.5f;
+        Gizmos.DrawLine(arrowPoint, arrowPoint + Quaternion.Euler(0, -30, 0) * -direction * 0.5f);
+        Gizmos.DrawLine(arrowPoint, arrowPoint + Quaternion.Euler(0, 30, 0) * -direction * 0.5f);
+    }
+
+    public void DrawPass(Vector3 start, Vector3 end, float duration = 3f)
+    {
+        lastPassStart = start;
+        lastPassEnd = end;
+        debugTimer = duration;
+    }
+}

+ 2 - 0
Assets/Scripts/FaceoffDebugVisualizer.cs.meta

@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: f14b1ad421ecd8049a10f2dceb90d17d

+ 42 - 11
Assets/Scripts/FaceoffManager.cs

@@ -201,28 +201,31 @@ public class FaceoffManager : MonoBehaviour
 
         if (target != null && target != winner)
         {
-            Debug.Log($"Puck sent to {target.stats.playerName}");
+            Debug.Log($"Puck sent to {target.stats.playerName} at position {target.transform.position}");
 
             // Calculate direction from FACEOFF SPOT (not puck position, since puck might be carried)
             Vector3 startPosition = currentFaceoffSpot.position;
             Vector3 targetPosition = target.transform.position;
+
+            // Keep pass flat on the ice (ignore Y difference)
+            startPosition.y = 0.025f;
+            targetPosition.y = 0.025f;
+
             Vector3 passDirection = (targetPosition - startPosition).normalized;
 
             float distance = Vector3.Distance(startPosition, targetPosition);
             float adjustedForce = passForce * Mathf.Clamp(distance / 5f, 0.8f, 2f);
 
+            Debug.Log($"Pass direction: {passDirection}, Distance: {distance:F2}m, Force: {adjustedForce:F2}");
+
             // Make sure puck is free and at faceoff spot
             if (puck != null)
             {
                 puck.Release();
-                puck.transform.position = startPosition + Vector3.up * 0.025f;
 
-                // Apply force
-                puck.ApplyForce(passDirection * adjustedForce, ForceMode.Impulse);
+                // Wait one frame to ensure Release() completes
+                StartCoroutine(ExecutePassAfterFrame(startPosition, passDirection, adjustedForce, target));
             }
-
-            // Delay assignment to let puck travel
-            StartCoroutine(AssignPuckAfterDelay(target, 0.3f));
         }
         else
         {
@@ -234,6 +237,34 @@ public class FaceoffManager : MonoBehaviour
         }
     }
 
+    private IEnumerator ExecutePassAfterFrame(Vector3 startPosition, Vector3 direction, float force, PlayerController target)
+    {
+        yield return new WaitForFixedUpdate(); // Wait for physics to settle
+
+        if (puck != null)
+        {
+            // Position puck at faceoff spot
+            puck.transform.position = startPosition;
+
+            // Get rigidbody and zero everything
+            Rigidbody puckRb = puck.GetComponent<Rigidbody>();
+            if (puckRb != null)
+            {
+                puckRb.linearVelocity = Vector3.zero;
+                puckRb.angularVelocity = Vector3.zero;
+
+                // Apply force in next physics frame
+                yield return new WaitForFixedUpdate();
+                puckRb.AddForce(direction * force, ForceMode.VelocityChange);
+
+                Debug.Log($"Applied force: {direction * force}");
+            }
+        }
+
+        // Delay assignment to let puck travel
+        StartCoroutine(AssignPuckAfterDelay(target, 0.5f));
+    }
+
     private IEnumerator AssignPuckAfterDelay(PlayerController target, float delay)
     {
         yield return new WaitForSeconds(delay);
@@ -243,14 +274,14 @@ public class FaceoffManager : MonoBehaviour
         {
             float distance = Vector3.Distance(puck.transform.position, target.transform.position);
 
-            if (distance < 3f) // Increased pickup range
+            if (distance < 4f) // Increased pickup range further
             {
                 // Stop the puck's movement before assigning
                 Rigidbody puckRb = puck.GetComponent<Rigidbody>();
                 if (puckRb != null)
                 {
-                    puckRb.linearVelocity *= 0.3f; // Slow down significantly
-                    puckRb.angularVelocity = Vector3.zero; // Stop spinning
+                    puckRb.linearVelocity = Vector3.zero;
+                    puckRb.angularVelocity = Vector3.zero;
                 }
 
                 puck.AssignToPlayer(target);
@@ -258,7 +289,7 @@ public class FaceoffManager : MonoBehaviour
             }
             else
             {
-                Debug.Log($"Puck too far from {target.stats.playerName} ({distance:F1}m)");
+                Debug.Log($"Puck too far from {target.stats.playerName} ({distance:F1}m) - Puck at {puck.transform.position}, Target at {target.transform.position}");
             }
         }
     }

+ 101 - 0
Assets/Scripts/GameSetup.cs

@@ -0,0 +1,101 @@
+using UnityEngine;
+
+public class GameSetup : MonoBehaviour
+{
+    [Header("Auto Setup")]
+    [SerializeField] private bool setupOnAwake = true;
+    [SerializeField] private bool createLayersIfMissing = true;
+
+    void Awake()
+    {
+        if (setupOnAwake)
+        {
+            SetupPhysicsLayers();
+            AssignLayers();
+        }
+    }
+
+    void SetupPhysicsLayers()
+    {
+        // Layer 6 = Player
+        // Layer 7 = Puck
+        // Layer 8 = Rink
+
+        // Puck passes through players (we'll add interception logic separately)
+        Physics.IgnoreLayerCollision(6, 7, true); // Player <-> Puck = ignore collision
+
+        // Players still collide with each other
+        Physics.IgnoreLayerCollision(6, 6, false); // Player <-> Player = collide
+
+        // Players collide with rink
+        Physics.IgnoreLayerCollision(6, 8, false); // Player <-> Rink = collide
+
+        // Puck collides with rink
+        Physics.IgnoreLayerCollision(7, 8, false); // Puck <-> Rink = collide
+
+        Debug.Log("✓ Physics layers configured: Puck will pass through players");
+    }
+
+    void AssignLayers()
+    {
+        int playerLayer = LayerMask.NameToLayer("Player");
+        int puckLayer = LayerMask.NameToLayer("Puck");
+        int rinkLayer = LayerMask.NameToLayer("Rink");
+
+        // Check if layers exist
+        if (playerLayer == -1 || puckLayer == -1 || rinkLayer == -1)
+        {
+            Debug.LogWarning("⚠ Layers not found! Please create them manually:");
+            Debug.LogWarning("Edit → Project Settings → Tags and Layers");
+            Debug.LogWarning("Set Layer 6 = 'Player', Layer 7 = 'Puck', Layer 8 = 'Rink'");
+            return;
+        }
+
+        // Assign all players to Player layer (6)
+        PlayerController[] players = FindObjectsByType<PlayerController>(FindObjectsSortMode.None);
+        foreach (var player in players)
+        {
+            SetLayerRecursively(player.gameObject, playerLayer);
+        }
+        Debug.Log($"✓ Assigned {players.Length} players to Player layer");
+
+        // Assign puck to Puck layer (7)
+        PuckController puck = FindFirstObjectByType<PuckController>();
+        if (puck != null)
+        {
+            SetLayerRecursively(puck.gameObject, puckLayer);
+            Debug.Log("✓ Assigned Puck to Puck layer");
+        }
+
+        // Find rink objects (anything with "Rink", "Ice", "Board" in name)
+        GameObject[] allObjects = FindObjectsByType<GameObject>(FindObjectsSortMode.None);
+        int rinkCount = 0;
+        foreach (var obj in allObjects)
+        {
+            string nameLower = obj.name.ToLower();
+            if (nameLower.Contains("rink") || nameLower.Contains("ice") ||
+                nameLower.Contains("board") || nameLower.Contains("surface"))
+            {
+                SetLayerRecursively(obj, rinkLayer);
+                rinkCount++;
+            }
+        }
+        Debug.Log($"✓ Assigned {rinkCount} rink objects to Rink layer");
+    }
+
+    void SetLayerRecursively(GameObject obj, int layer)
+    {
+        obj.layer = layer;
+        foreach (Transform child in obj.transform)
+        {
+            SetLayerRecursively(child.gameObject, layer);
+        }
+    }
+
+    [ContextMenu("Setup Now")]
+    public void SetupNow()
+    {
+        SetupPhysicsLayers();
+        AssignLayers();
+    }
+}

+ 2 - 0
Assets/Scripts/GameSetup.cs.meta

@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: ad6fce936a4619748818b1c4df3b1369

+ 49 - 0
Assets/Scripts/LayerAssigner.cs

@@ -0,0 +1,49 @@
+using UnityEngine;
+
+[ExecuteInEditMode]
+public class LayerAssigner : MonoBehaviour
+{
+    [Header("Auto-assign layers")]
+    [SerializeField] private bool autoAssign = true;
+
+    void Start()
+    {
+        if (autoAssign)
+        {
+            AssignLayers();
+        }
+    }
+
+    [ContextMenu("Assign Layers Now")]
+    public void AssignLayers()
+    {
+        // Assign all players to Player layer (6)
+        PlayerController[] players = FindObjectsByType<PlayerController>(FindObjectsSortMode.None);
+        foreach (var player in players)
+        {
+            player.gameObject.layer = LayerMask.NameToLayer("Player");
+            Debug.Log($"Assigned {player.stats.playerName} to Player layer");
+        }
+
+        // Assign puck to Puck layer (7)
+        PuckController puck = FindFirstObjectByType<PuckController>();
+        if (puck != null)
+        {
+            puck.gameObject.layer = LayerMask.NameToLayer("Puck");
+            Debug.Log("Assigned Puck to Puck layer");
+        }
+
+        // Find rink objects (anything with "Rink" or "Ice" in name)
+        GameObject[] allObjects = FindObjectsByType<GameObject>(FindObjectsSortMode.None);
+        foreach (var obj in allObjects)
+        {
+            if (obj.name.ToLower().Contains("rink") || obj.name.ToLower().Contains("ice"))
+            {
+                obj.layer = LayerMask.NameToLayer("Rink");
+                Debug.Log($"Assigned {obj.name} to Rink layer");
+            }
+        }
+
+        Debug.Log("Layer assignment complete!");
+    }
+}

+ 2 - 0
Assets/Scripts/LayerAssigner.cs.meta

@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 3e0fc48da7df99549b73d84673f66d74

+ 79 - 10
Assets/Scripts/PuckController.cs

@@ -16,6 +16,15 @@ public class PuckController : MonoBehaviour
     [SerializeField] private Material normalMaterial;
     [SerializeField] private Material possessedMaterial;
 
+    [Header("Interception Settings")]
+    [SerializeField] private bool canBeIntercepted = true;
+    [SerializeField] private float interceptionCheckRadius = 0.5f;
+    [SerializeField] private LayerMask playerLayer;
+
+    private bool isPassActive = false;
+    private float passStartTime = 0f;
+    private float passProtectionTime = 0.1f; // Short window where pass can't be intercepted
+
     private Rigidbody rb;
     private MeshRenderer meshRenderer;
     private PlayerController currentCarrier;
@@ -45,21 +54,29 @@ public class PuckController : MonoBehaviour
         rb.collisionDetectionMode = CollisionDetectionMode.Continuous;
         rb.interpolation = RigidbodyInterpolation.Interpolate;
 
+        // IMPORTANT: Make sure puck is NOT kinematic at start
+        rb.isKinematic = false;
+
+        // Freeze rotation on X and Z to keep puck flat
+        rb.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationZ;
+
         // Set up collider if not present
         SphereCollider collider = GetComponent<SphereCollider>();
         if (collider == null)
         {
             collider = gameObject.AddComponent<SphereCollider>();
-            collider.radius = 0.038f; // ~76mm diameter regulation puck
         }
 
+        collider.radius = 0.038f; // ~76mm diameter regulation puck
+        collider.isTrigger = false; // MUST be false for physics collisions
+
         // Create physics material for ice-like behavior
         PhysicsMaterial puckPhysicsMaterial = new PhysicsMaterial("PuckPhysics");
         puckPhysicsMaterial.dynamicFriction = friction;
         puckPhysicsMaterial.staticFriction = friction;
-        puckPhysicsMaterial.bounciness = 0.2f;
+        puckPhysicsMaterial.bounciness = 0.1f; // Reduced bounce
         puckPhysicsMaterial.frictionCombine = PhysicsMaterialCombine.Minimum;
-        puckPhysicsMaterial.bounceCombine = PhysicsMaterialCombine.Average;
+        puckPhysicsMaterial.bounceCombine = PhysicsMaterialCombine.Minimum; // Changed to Minimum
         collider.material = puckPhysicsMaterial;
     }
 
@@ -89,10 +106,8 @@ public class PuckController : MonoBehaviour
             targetCarryPosition = currentCarrier.transform.position + carrierForward * carrierOffset;
             targetCarryPosition.y = 0.025f;
 
-            // Instant positioning while carried (no lerp to prevent lag)
             transform.position = targetCarryPosition;
 
-            // Make absolutely sure no velocity while carried
             if (rb != null)
             {
                 rb.linearVelocity = Vector3.zero;
@@ -101,6 +116,12 @@ public class PuckController : MonoBehaviour
         }
         else
         {
+            // Check for interceptions during passes
+            if (isPassActive && canBeIntercepted)
+            {
+                CheckForInterception();
+            }
+
             // Keep puck at proper height on ice when loose
             if (transform.position.y < 0.025f)
             {
@@ -108,7 +129,6 @@ public class PuckController : MonoBehaviour
                 pos.y = 0.025f;
                 transform.position = pos;
 
-                // Dampen vertical velocity
                 if (rb != null)
                 {
                     Vector3 vel = rb.linearVelocity;
@@ -118,16 +138,61 @@ public class PuckController : MonoBehaviour
                         rb.linearVelocity = vel;
                     }
 
-                    // Dampen excessive spinning
                     if (rb.angularVelocity.magnitude > 10f)
                     {
                         rb.angularVelocity *= 0.9f;
                     }
                 }
             }
+
+            // End pass if puck has slowed down
+            if (isPassActive && rb != null && rb.linearVelocity.magnitude < 1f)
+            {
+                isPassActive = false;
+            }
         }
     }
+    private void CheckForInterception()
+    {
+        // Skip interception check during protection window
+        if (Time.time - passStartTime < passProtectionTime)
+            return;
 
+        // Find nearby players
+        Collider[] nearbyColliders = Physics.OverlapSphere(transform.position, interceptionCheckRadius, playerLayer);
+
+        foreach (var col in nearbyColliders)
+        {
+            PlayerController player = col.GetComponent<PlayerController>();
+            if (player != null && player.CanPickupPuck())
+            {
+                // Calculate interception chance based on player stats and positioning
+                float interceptChance = CalculateInterceptionChance(player);
+
+                if (Random.value < interceptChance)
+                {
+                    Debug.Log($"{player.stats.playerName} intercepts the pass!");
+                    AssignToPlayer(player);
+                    isPassActive = false;
+                    break;
+                }
+            }
+        }
+    }
+    private float CalculateInterceptionChance(PlayerController player)
+    {
+        // Base chance very low (5%)
+        float baseChance = 0.05f;
+
+        // Increase based on awareness and stick handling
+        float statBonus = (player.stats.awareness + player.stats.stickHandling) / 200f * 0.1f;
+
+        // Increase if player is facing the puck
+        Vector3 toPuck = (transform.position - player.transform.position).normalized;
+        float facingBonus = Vector3.Dot(player.transform.forward, toPuck) * 0.05f;
+
+        return Mathf.Clamp01(baseChance + statBonus + facingBonus);
+    }
     public void AssignToPlayer(PlayerController player)
     {
         if (currentCarrier != null)
@@ -180,8 +245,12 @@ public class PuckController : MonoBehaviour
 
     public void ApplyForce(Vector3 force, ForceMode mode = ForceMode.Impulse)
     {
-        Release(); // Free the puck first
+        Release();
         rb.AddForce(force, mode);
+
+        // Mark as active pass
+        isPassActive = true;
+        passStartTime = Time.time;
     }
 
     public void SetVelocity(Vector3 velocity)
@@ -213,8 +282,8 @@ public class PuckController : MonoBehaviour
     // Physics collision - check if any player can pick up the puck
     void OnTriggerStay(Collider other)
     {
-        // Only auto-pickup if puck is moving slowly (not during passes)
-        if (IsLoose && rb != null && rb.linearVelocity.magnitude < 2f)
+        // Only auto-pickup if puck is NOT in active pass and moving slowly
+        if (IsLoose && !isPassActive && rb != null && rb.linearVelocity.magnitude < 2f)
         {
             PlayerController player = other.GetComponent<PlayerController>();
             if (player != null && player.CanPickupPuck())

+ 3 - 3
ProjectSettings/TagManager.asset

@@ -13,9 +13,9 @@ TagManager:
   - 
   - Water
   - UI
-  - 
-  - 
-  - 
+  - Player
+  - Puck
+  - Rink
   - 
   - 
   -