using UnityEngine; using UnityEngine.UI; public class MinimapManager : MonoBehaviour { [Header("Camera/RenderTexture Settings")] [Tooltip("Optional: If set, the minimap camera will render into this RenderTexture.")] public RenderTexture targetTexture; [Tooltip("Optional: If set, this RawImage's texture will be assigned to the target RenderTexture.")] public RawImage targetRawImage; [Tooltip("Layers rendered by the minimap camera (include 'Minimap' layer here).")] public LayerMask cullingMask = ~0; [Header("Follow Settings")] public Vector3 offset = new Vector3(0f, 50f, 0f); [Tooltip("GTA V style: map rotates with player heading, player icon stays centered pointing up.")] public bool rotateWithPlayer = true; [Tooltip("How fast the minimap rotation follows the player heading. Higher = snappier.")] public float rotationSmoothSpeed = 10f; [Header("Zoom Settings")] public float defaultZoom = 50f; public float zoomLerpSpeed = 5f; private Transform player; private Camera minimapCam; private float targetZoom; private bool isCashSystemMode = false; private float refreshTimer = 0f; private float refreshInterval = 1f; /// /// The camera's current smoothed Y heading angle. /// MinimapMarker reads this to match the player chevron rotation exactly. /// public static float SmoothedHeading { get; private set; } void Awake() { minimapCam = GetComponent(); if (minimapCam == null) { Debug.LogError("MinimapManager must be placed on a Camera object."); enabled = false; return; } minimapCam.orthographic = true; minimapCam.orthographicSize = defaultZoom; minimapCam.nearClipPlane = 0.01f; minimapCam.farClipPlane = 1000f; minimapCam.clearFlags = CameraClearFlags.SolidColor; minimapCam.backgroundColor = new Color(0, 0, 0, 0); // Ensure Minimap layer is visible int minimapLayer = LayerMask.NameToLayer("Minimap"); if (minimapLayer >= 0) { cullingMask |= (1 << minimapLayer); Debug.Log($"[MinimapManager] Found Minimap layer: {minimapLayer}"); } else { // FALLBACK: If Minimap layer doesn't exist, use layer 31 (where markers fall back to) cullingMask |= (1 << 31); Debug.LogWarning("[MinimapManager] 'Minimap' layer not found! Using layer 31 fallback. " + "Create 'Minimap' layer in Project Settings for best results."); } // Legacy layer support int iconsLayer = LayerMask.NameToLayer("minimapIcons"); if (iconsLayer >= 0) { cullingMask |= (1 << iconsLayer); } minimapCam.cullingMask = cullingMask; if (targetTexture != null) { minimapCam.targetTexture = targetTexture; if (targetRawImage != null) { targetRawImage.texture = targetTexture; } } targetZoom = defaultZoom; } void Start() { // Check game mode isCashSystemMode = SelectionOptions.Instance != null && SelectionOptions.Instance.isCashSystemSelected; FindPlayer(); // IMPORTANT: Ensure MinimapMarkerManager exists for markers in ALL modes MinimapMarkerManager.EnsureExists(); // Create edge indicators for off-screen entities if (targetRawImage != null) { MinimapEdgeIndicator.AttachTo(targetRawImage.rectTransform); // Add click-to-expand controller if (targetRawImage.GetComponent() == null) targetRawImage.gameObject.AddComponent(); } Debug.Log($"[MinimapManager] Initialized - Cash System Mode: {isCashSystemMode}. Using Markers Only."); Debug.Log("[MinimapManager] IMPORTANT: Main Camera must EXCLUDE 'Minimap' layer from Culling Mask!"); } void LateUpdate() { if (player == null) { // Try to find player periodically FindPlayer(); return; } // Periodic check to switch targets if control changed refreshTimer += Time.deltaTime; if (refreshTimer >= refreshInterval) { refreshTimer = 0f; FindPlayer(); } // --- Camera follow --- transform.position = player.position + offset; if (rotateWithPlayer) { // Smooth rotation for GTA V feel — no jerky snapping Quaternion targetRotation = Quaternion.Euler(90f, player.eulerAngles.y, 0f); transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * rotationSmoothSpeed); // Expose the ACTUAL smoothed angle so markers can match perfectly SmoothedHeading = transform.eulerAngles.y; } else { transform.rotation = Quaternion.Euler(90f, 0f, 0f); SmoothedHeading = 0f; } // Smooth zoom minimapCam.orthographicSize = Mathf.Lerp( minimapCam.orthographicSize, targetZoom, Time.deltaTime * zoomLerpSpeed ); } private void FindPlayer() { PlayerControllerNewRohan playerController = FindObjectOfType(); if (playerController != null) { player = playerController.transform; return; } GameObject p = GameObject.FindGameObjectWithTag("Player"); if (p != null) { player = p.transform; } } // === Public APIs === public void SetTarget(Transform newTarget) { player = newTarget; } public void SetZoom(float zoomSize) { targetZoom = Mathf.Max(1f, zoomSize); } public void ZoomIn(float amount = 5f) { SetZoom(targetZoom - amount); } public void ZoomOut(float amount = 5f) { SetZoom(targetZoom + amount); } // Kept for compatibility, but does nothing now as markers manage themselves public void ForceRefresh() { FindPlayer(); } }