using UnityEngine; /// /// Teams mode: a central capture zone. The local player sends "inZone" messages /// to the server while inside the zone. The server tallies scores. /// Visualizes zone control by tinting the zone's renderer. /// /// Setup: Create a flat Box/Plane in the center of the arena. /// Add a BoxCollider set to "Is Trigger". Attach this script. /// public class ZoneCapture : MonoBehaviour { public static ZoneCapture Instance { get; private set; } [Header("Visual")] [Tooltip("Neutral zone color")] public Color neutralColor = new Color(0.5f, 0.5f, 0.6f, 0.5f); [Tooltip("Red team controls color")] public Color redColor = new Color(1f, 0.2f, 0.2f, 0.6f); [Tooltip("Blue team controls color")] public Color blueColor = new Color(0.2f, 0.5f, 1f, 0.6f); [Header("Score Reporting")] [Tooltip("How often (seconds) to send inZone=true to server while inside")] public float reportInterval = 0.5f; private bool _isLocalPlayerInZone = false; private float _reportTimer = 0f; private Renderer _renderer; // Zone occupant counts (received via server state — approximated by remote player positions) private int _redInZone = 0; private int _blueInZone = 0; void Awake() { Instance = this; _renderer = GetComponent(); SetZoneColor(neutralColor); } void Start() { if (NetworkManager.Instance != null) { NetworkManager.Instance.OnPhaseChanged += OnPhaseChanged; } } void OnDestroy() { if (NetworkManager.Instance != null) NetworkManager.Instance.OnPhaseChanged -= OnPhaseChanged; } void OnPhaseChanged(string phase) { if (phase == "lobby" || phase == "roundEnd") { _isLocalPlayerInZone = false; _redInZone = 0; _blueInZone = 0; SetZoneColor(neutralColor); } } void Update() { if (!_isLocalPlayerInZone) return; _reportTimer += Time.deltaTime; if (_reportTimer >= reportInterval) { _reportTimer = 0f; NetworkManager.Instance?.SendInZone(true); } // Update zone tint based on dominance UpdateZoneColor(); } void OnTriggerEnter(Collider other) { if (other.GetComponent() != null) { _isLocalPlayerInZone = true; _reportTimer = 0f; NetworkManager.Instance?.SendInZone(true); } // Count remote players in zone var remote = other.GetComponent(); if (remote != null) { // team info would need to be tracked — skip for now, server handles scoring } } void OnTriggerExit(Collider other) { if (other.GetComponent() != null) { _isLocalPlayerInZone = false; NetworkManager.Instance?.SendInZone(false); } } private void UpdateZoneColor() { // Read team scores from NetworkManager state for visual feedback // For now use a pulsing neutral tint when local player is inside float pulse = 0.7f + 0.3f * Mathf.Sin(Time.time * 3f); Color c = neutralColor; c.a = pulse * 0.6f; SetZoneColor(c); } public void SetZoneColor(Color c) { if (_renderer == null) return; var mat = _renderer.material; if (mat.HasProperty("_BaseColor")) mat.SetColor("_BaseColor", c); else mat.color = c; } }