/
arti4
/
Diplom
Обзор
Документация
Войти
/
arti4
/
Diplom
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
Scripts/Other/Map/MiniMapController.cs
652 строки
19 KB
arti4
Загрузка всех скриптов
17 май 2026, 09:08
Верифицирован
17 май 2026, 09:08
cc2e1cd
Код
Авторство
О чём код?
using UnityEngine; using UnityEngine.UI; using System.Collections.Generic; public class MiniMapController : MonoBehaviour { [Header("Основные настройки")] [SerializeField] private Transform playerTransform; [SerializeField] private float cameraHeight = 100f; [Header("UI Elements")] [SerializeField] private RectTransform miniMapRect; [SerializeField] private RectTransform playerArrow; [SerializeField] private GameObject enemyArrowPrefab; [Header("Настройки карты")] [SerializeField] private float mapRadius = 50f; [SerializeField] private float uiRadius = 100f; [SerializeField] private float enemyArrowHeight = 5f; [Header("Внешние объекты")] [SerializeField] private string enemyTag = "Enemy"; [SerializeField] private LayerMask miniMapLayer = 31; [Header("Маркеры")] [SerializeField] private GameObject markerContainer; [Header("Маркеры на краю карты")] [SerializeField] private GameObject edgeMarkerPrefab; [SerializeField] private Color edgeMarkerColor = Color.white; [SerializeField] private float edgeMarkerMinScale = 0.3f; [SerializeField] private float edgeMarkerMaxScale = 0.8f; [SerializeField] private float edgeMarkerDistance = 85f; [SerializeField] private float maxMarkerDistance = 500f; private int frameCounter = 0; [Header("Количество кадров")] [SerializeField] private int updateInterval = 3; private List<GameObject> edgeMarkerObjects = new List<GameObject>(); private Transform edgeMarkersContainer; private List<RaceMarker> raceMarkers = new List<RaceMarker>(); private Camera miniMapCamera; private List<Transform> enemies; private List<GameObject> enemyArrowObjects; private Transform enemyArrowsContainer; private bool isInitialized = false; private int miniMapLayerIndex; void Awake() { if (miniMapRect == null) miniMapRect = GetComponent<RectTransform>(); EnsureContainersExist(); } void EnsureContainersExist() { if (enemyArrowsContainer == null) { enemyArrowsContainer = MarkerContainersManager.Instance.GetEnemyArrowsContainer(); } if (edgeMarkersContainer == null) { edgeMarkersContainer = MarkerContainersManager.Instance.GetEdgeMarkersContainer(); } } void Start() { Initialize(); ForceRegisterAllRaceMarkers(); Invoke(nameof(ForceUpdateAllMarkersRotation), 0.5f); Invoke(nameof(ForceUpdateAllMarkersRotation), 1.0f); if (enemyArrowsContainer != null) { enemyArrowsContainer.rotation = Quaternion.identity; } if (edgeMarkersContainer != null) { edgeMarkersContainer.rotation = Quaternion.identity; } Transform markerContainer = GetMarkerContainer(); if (markerContainer != null) { markerContainer.rotation = Quaternion.identity; } StartCoroutine(DelayedRotationUpdate()); } public void ForceUpdateAllMarkersRotation() { RaceMarker[] allMarkers = FindObjectsByType<RaceMarker>(FindObjectsSortMode.None); foreach (RaceMarker marker in allMarkers) { if (marker != null) { marker.ForceUpdateRotation(); } } } public void ForceRegisterAllRaceMarkers() { RaceMarker[] allMarkers = FindObjectsByType<RaceMarker>(FindObjectsSortMode.None); foreach (RaceMarker marker in allMarkers) { if (marker != null && !raceMarkers.Contains(marker)) { raceMarkers.Add(marker); } } UpdateEdgeMarkers(); } public void UnregisterRaceMarker(RaceMarker raceMarker) { if (raceMarkers.Contains(raceMarker)) { raceMarkers.Remove(raceMarker); } } void UpdateEdgeMarkers() { if (miniMapCamera == null || edgeMarkersContainer == null || playerTransform == null) return; ClearEdgeMarkers(); MapMarkerManager markerManager = FindFirstObjectByType<MapMarkerManager>(); if (markerManager == null) return; var playerMarkers = markerManager.GetAllMarkers(); foreach (var marker in playerMarkers) { if (marker?.worldObject == null) continue; Vector3 markerWorldPos = marker.worldObject.transform.position; Vector2 playerPos2D = new Vector2(playerTransform.position.x, playerTransform.position.z); Vector2 markerPos2D = new Vector2(markerWorldPos.x, markerWorldPos.z); float distance = Vector2.Distance(playerPos2D, markerPos2D); if (distance > maxMarkerDistance) continue; Vector3 viewportPos = miniMapCamera.WorldToViewportPoint(markerWorldPos); bool isVisible = viewportPos.x >= 0 && viewportPos.x <= 1 && viewportPos.y >= 0 && viewportPos.y <= 1 && viewportPos.z > 0; if (!isVisible) { CreateEdgeMarker(markerWorldPos, distance); } } } void CreateEdgeMarker(Vector3 markerWorldPos, float distance) { if (edgeMarkerPrefab == null) return; Vector3 direction = markerWorldPos - playerTransform.position; direction.y = 0; if (direction.magnitude < 0.1f) { direction = Vector3.forward; } direction.Normalize(); Vector3 edgePosition = playerTransform.position + direction * edgeMarkerDistance; edgePosition.y = enemyArrowHeight; GameObject edgeMarker = Instantiate(edgeMarkerPrefab, edgeMarkersContainer); edgeMarker.transform.position = edgePosition; if (miniMapLayerIndex != -1) { edgeMarker.layer = miniMapLayerIndex; SetLayerRecursively(edgeMarker.transform, miniMapLayerIndex); } Vector3 lookDirection = markerWorldPos - edgePosition; lookDirection.y = 0; if (lookDirection != Vector3.zero) { Quaternion targetRotation = Quaternion.LookRotation(lookDirection); edgeMarker.transform.rotation = Quaternion.Euler(90f, targetRotation.eulerAngles.y, 0f); } else { edgeMarker.transform.rotation = Quaternion.Euler(90f, 0f, 0f); } float distanceRatio = Mathf.Clamp01(1f - (distance / maxMarkerDistance)); float scale = Mathf.Lerp(edgeMarkerMinScale, edgeMarkerMaxScale, distanceRatio); edgeMarker.transform.localScale = Vector3.one * scale; Renderer renderer = edgeMarker.GetComponent<Renderer>(); if (renderer != null) { Color finalColor = edgeMarkerColor; finalColor.a = Mathf.Lerp(0.7f, 1f, distanceRatio); renderer.material.color = finalColor; } else { Image image = edgeMarker.GetComponent<Image>(); if (image != null) { Color finalColor = edgeMarkerColor; finalColor.a = Mathf.Lerp(0.7f, 1f, distanceRatio); image.color = finalColor; } } edgeMarkerObjects.Add(edgeMarker); } void ClearEdgeMarkers() { foreach (GameObject edgeMarker in edgeMarkerObjects) { if (edgeMarker != null) Destroy(edgeMarker); } edgeMarkerObjects.Clear(); } void Initialize() { if (isInitialized) return; miniMapCamera = GetComponent<Camera>(); enemies = new List<Transform>(); enemyArrowObjects = new List<GameObject>(); CreateEnemyArrowsContainer(); CreateEdgeMarkersContainer(); miniMapLayerIndex = LayerMask.NameToLayer("MiniMapEnemyArrow"); if (miniMapLayerIndex == -1) { miniMapLayerIndex = (int)Mathf.Log(miniMapLayer.value, 2); } if (playerArrow != null) { Image img = playerArrow.GetComponent<Image>(); playerArrow.localEulerAngles = Vector3.zero; } if (enemyArrowPrefab == null) { Debug.LogError("Не назначен enemyArrowPrefab! Создайте префаб стрелки врага."); return; } FindInitialEnemies(); isInitialized = true; } void TryFindPlayer() { if (playerTransform != null && !playerTransform.name.StartsWith("PlayerCar_")) { Debug.LogWarning($"[MiniMap] Сбрасываем НЕПРАВИЛЬНЫЙ playerTransform: {playerTransform.name}"); playerTransform = null; } if (playerTransform == null) { GameObject[] allObjects = FindObjectsByType<GameObject>(FindObjectsSortMode.None); GameObject player = null; foreach (GameObject obj in allObjects) { if (obj.name.StartsWith("PlayerCar_")) { player = obj; Debug.Log($"[MiniMap] ✓ Игрок НАЙДЕН по имени: {player.name}"); break; } } if (player != null) { playerTransform = player.transform; Debug.Log($"[MiniMap] Игрок установлен: {player.name}"); } else { if (Time.frameCount % 120 == 0) Debug.LogWarning("[MiniMap] Игрок (PlayerCar_*) не найден!"); } } } void CreateEnemyArrowsContainer() { enemyArrowsContainer = MarkerContainersManager.Instance.GetEnemyArrowsContainer(); enemyArrowsContainer.gameObject.layer = miniMapLayerIndex; } void CreateEdgeMarkersContainer() { edgeMarkersContainer = MarkerContainersManager.Instance.GetEdgeMarkersContainer(); } public Transform GetMarkerContainer() { return MarkerContainersManager.Instance.GetMiniMapMarkersContainer(); } void FindInitialEnemies() { GameObject[] enemyObjects = GameObject.FindGameObjectsWithTag(enemyTag); foreach (GameObject enemyObj in enemyObjects) { if (enemyObj != null) { AddEnemy(enemyObj.transform); } } } void Update() { frameCounter++; if (frameCounter % 50 == 0) { LogCameraTarget(); } if (frameCounter % updateInterval != 0) return; TryFindPlayer(); if (!isInitialized || playerTransform == null) return; UpdateCameraPosition(); UpdatePlayerArrow(); UpdateEnemyArrows(); UpdateEdgeMarkers(); } public void SetUpdateInterval(int interval) { updateInterval = Mathf.Max(1, interval); } void UpdateCameraPosition() { Vector3 newPos = playerTransform.position; newPos.y = cameraHeight; transform.position = newPos; transform.rotation = Quaternion.Euler(90f, playerTransform.eulerAngles.y, 0f); } void UpdatePlayerArrow() { if (playerArrow == null) return; playerArrow.anchoredPosition = Vector2.zero; playerArrow.localEulerAngles = Vector3.zero; } void UpdateEnemyArrows() { if (enemies == null || enemyArrowObjects == null || enemyArrowsContainer == null) return; for (int i = 0; i < enemies.Count; i++) { if (enemies[i] == null) { if (i < enemyArrowObjects.Count && enemyArrowObjects[i] != null) enemyArrowObjects[i].SetActive(false); continue; } if (i < enemyArrowObjects.Count && enemyArrowObjects[i] != null && !enemyArrowObjects[i].activeSelf) enemyArrowObjects[i].SetActive(true); if (i < enemyArrowObjects.Count && enemyArrowObjects[i] != null) { Transform enemy = enemies[i]; Transform arrowTransform = enemyArrowObjects[i].transform; Vector3 enemyPos = enemy.position; arrowTransform.position = new Vector3( enemyPos.x, enemyArrowHeight, enemyPos.z ); Vector3 enemyRotation = enemy.eulerAngles; arrowTransform.rotation = Quaternion.Euler( 90f, enemyRotation.y, 0f ); } } } public void AddEnemy(Transform enemy) { if (enemy == null) { return; } for (int i = 0; i < enemies.Count; i++) { if (enemies[i] == enemy) { return; } } enemies.Add(enemy); if (enemyArrowPrefab != null && enemyArrowsContainer != null) { GameObject arrowObj = Instantiate(enemyArrowPrefab, enemyArrowsContainer); arrowObj.name = $"EnemyArrow_{enemy.name}"; arrowObj.layer = miniMapLayerIndex; SetLayerRecursively(arrowObj.transform, miniMapLayerIndex); Vector3 enemyPos = enemy.position; arrowObj.transform.position = new Vector3( enemyPos.x, enemyArrowHeight, enemyPos.z ); arrowObj.transform.rotation = Quaternion.Euler(90f, enemy.eulerAngles.y, 0f); Renderer renderer = arrowObj.GetComponent<Renderer>(); if (renderer != null) { renderer.material.color = Color.red; } else { Image image = arrowObj.GetComponent<Image>(); if (image != null) { image.color = Color.red; } } enemyArrowObjects.Add(arrowObj); arrowObj.SetActive(true); } else { enemyArrowObjects.Add(null); } } private void SetLayerRecursively(Transform obj, int layerIndex) { obj.gameObject.layer = layerIndex; foreach (Transform child in obj) { SetLayerRecursively(child, layerIndex); } } public void RegisterRaceMarker(RaceMarker raceMarker) { MapMarkerManager markerManager = FindFirstObjectByType<MapMarkerManager>(); if (markerManager != null) { var playerMarkers = markerManager.GetAllMarkers(); bool isPlayerMarker = false; foreach (var marker in playerMarkers) { if (marker.miniMapObject == raceMarker.gameObject) { isPlayerMarker = true; break; } } if (!isPlayerMarker) return; } if (raceMarker != null) { bool exists = false; foreach (var existing in raceMarkers) { if (existing != null && existing.gameObject == raceMarker.gameObject) { exists = true; break; } } if (!exists) { raceMarkers.Add(raceMarker); } } } public void ForceRefreshRaceMarkers() { RaceMarker[] allMarkers = FindObjectsByType<RaceMarker>(FindObjectsSortMode.None); foreach (RaceMarker marker in allMarkers) { if (marker != null && !raceMarkers.Contains(marker)) { raceMarkers.Add(marker); } } } void CreateEdgeMarkerForRaceMarker(RaceMarker raceMarker) { if (raceMarker == null || raceMarker.transform == null) return; } public void RemoveEnemy(Transform enemy) { if (!isInitialized || enemies == null) return; for (int i = 0; i < enemies.Count; i++) { if (enemies[i] == enemy) { if (i < enemyArrowObjects.Count && enemyArrowObjects[i] != null) { Destroy(enemyArrowObjects[i]); } enemies.RemoveAt(i); if (i < enemyArrowObjects.Count) enemyArrowObjects.RemoveAt(i); break; } } } public void ClearAllEnemyArrows() { if (enemyArrowObjects != null) { foreach (GameObject arrow in enemyArrowObjects) { if (arrow != null) Destroy(arrow); } enemyArrowObjects.Clear(); } if (enemies != null) enemies.Clear(); } void OnDestroy() { ClearAllEnemyArrows(); } public Transform GetPlayerTransform() { if (playerTransform != null) return playerTransform; GameObject player = GameObject.FindGameObjectWithTag("Player"); if (player != null) { playerTransform = player.transform; return playerTransform; } if (miniMapCamera != null) { } return null; } public List<Transform> GetEnemiesList() { return enemies; } void OnEnable() { StartCoroutine(DelayedRotationUpdate()); } System.Collections.IEnumerator DelayedRotationUpdate() { yield return new WaitForSeconds(0.1f); RaceMarker[] allMarkers = FindObjectsByType<RaceMarker>(FindObjectsSortMode.None); foreach (RaceMarker marker in allMarkers) { marker.ForceUpdateRotation(); } } void LogCameraTarget() { if (playerTransform != null) { Debug.Log($"[MiniMap Camera] Следит за: {playerTransform.name} | Position: {playerTransform.position} | Rotation Y: {playerTransform.eulerAngles.y}"); } else { Debug.LogWarning("[MiniMap Camera] Нет цели для отслеживания (playerTransform = null)"); } } }