/
arti4
/
Diplom
Обзор
Документация
Войти
/
arti4
/
Diplom
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
Scripts/Other/Map/MapMarkerManager.cs
1 161 строка
36 KB
arti4
Загрузка всех скриптов
17 май 2026, 09:08
Верифицирован
17 май 2026, 09:08
cc2e1cd
Код
Авторство
О чём код?
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class MapMarkerManager : MonoBehaviour { [Header("Префабы")] [SerializeField] private GameObject worldMarkerPrefab; [SerializeField] private GameObject miniMapMarkerPrefab; [SerializeField] private GameObject bigMapMarkerPrefab; [Header("Настройки высоты")] [SerializeField] private float worldMarkerHeight = 1f; [SerializeField] private float miniMapMarkerHeight = 20f; [SerializeField] private float bigMapMarkerHeight = 20f; [Header("Настройки слоев")] [SerializeField] private string worldMarkerLayerName = "Default"; [SerializeField] private string miniMapMarkerLayerName = "MiniMapEnemyArrow"; [SerializeField] private string bigMapMarkerLayerName = "MapEnemyArrow"; [Header("Настройки")] [SerializeField] private LayerMask groundLayer = -1; [SerializeField] private KeyCode createMarkerKey = KeyCode.Mouse1; [SerializeField] private KeyCode deleteMarkerKey = KeyCode.Mouse2; [Header("Настройки масштаба маркеров")] [SerializeField] private float markerScaleMultiplier = 0.5f; [SerializeField] private float defaultBigMapMarkerScale = 2.5f; [Header("Ссылки - ВАЖНО!")] [SerializeField] private MiniMapController miniMapController; [SerializeField] private BigMapController bigMapController; [SerializeField] private Camera bigMapCamera; [SerializeField] private RawImage bigMapRawImage; [SerializeField] private Canvas canvas; [SerializeField] private Camera uiCamera; [Header("Отладка")] [SerializeField] private bool enableDebug = true; [SerializeField] private Text debugText; [SerializeField] private GameObject debugSpherePrefab; private List<MapMarker> markers = new List<MapMarker>(); private Vector3 lastDebugWorldPos = Vector3.zero; MapMarker newMarker = new MapMarker(); [Header("Настройки удаления")] [SerializeField] private float markerClickTolerance = 1f; private int worldMarkerLayerIndex; private int miniMapMarkerLayerIndex; private int bigMapMarkerLayerIndex; [System.Serializable] public class MapMarker { public Vector3 worldPosition; public GameObject worldObject; public GameObject miniMapObject; public GameObject bigMapObject; } void Start() { InitializeLayers(); InitializeReferences(); } void Update() { if (!bigMapCamera.gameObject.activeInHierarchy || bigMapRawImage == null) { return; } UpdateDebugInfo(); if (Input.GetMouseButtonDown(1)) { bool isOverStandard = IsPointerOverBigMap(); bool isOverAlternative = IsPointerOverBigMapAlternative(); bool isOver = isOverAlternative; if (isOver) { Vector3 clickPosition = GetWorldPositionUnderMouse(); if (clickPosition != Vector3.zero) { if (TryDeleteMarkerAtMousePosition()) { } else { CreateMarker(clickPosition); ShowCreationFeedback(clickPosition); } } } } if (Input.GetMouseButtonDown(0) && bigMapCamera.gameObject.activeInHierarchy) { HandleMarkerClickForTeleport(); } if (Input.GetKey(KeyCode.LeftControl) && Input.GetMouseButtonDown(1)) { ClearAllMarkers(); } } bool TryDeleteMarkerAtMousePosition() { Vector3 mouseWorldPos = GetWorldPositionUnderMouse(); if (mouseWorldPos == Vector3.zero) return false; MapMarker nearestMarker = GetNearestMarker(mouseWorldPos); if (nearestMarker != null) { Vector2 markerPos2D = new Vector2(nearestMarker.worldPosition.x, nearestMarker.worldPosition.z); Vector2 mousePos2D = new Vector2(mouseWorldPos.x, mouseWorldPos.z); float distance = Vector2.Distance(markerPos2D, mousePos2D); if (distance <= markerClickTolerance) { int markerIndex = markers.IndexOf(nearestMarker); if (markerIndex >= 0) { RemoveMarker(markerIndex); ShowDeletionFeedback(mouseWorldPos); return true; } } } return false; } MapMarker GetNearestMarker(Vector3 position) { if (markers.Count == 0) return null; MapMarker nearestMarker = null; float minDistance = float.MaxValue; foreach (var marker in markers) { Vector2 markerPos2D = new Vector2(marker.worldPosition.x, marker.worldPosition.z); Vector2 clickPos2D = new Vector2(position.x, position.z); float distance = Vector2.Distance(markerPos2D, clickPos2D); if (distance < minDistance) { minDistance = distance; nearestMarker = marker; } } return nearestMarker; } void InitializeLayers() { worldMarkerLayerIndex = LayerMask.NameToLayer(worldMarkerLayerName); miniMapMarkerLayerIndex = LayerMask.NameToLayer(miniMapMarkerLayerName); bigMapMarkerLayerIndex = LayerMask.NameToLayer(bigMapMarkerLayerName); } void InitializeReferences() { if (bigMapCamera == null) bigMapCamera = Camera.main; if (canvas == null && bigMapRawImage != null) canvas = bigMapRawImage.GetComponentInParent<Canvas>(); if (uiCamera == null && canvas != null) uiCamera = canvas.worldCamera; } private void HandleMarkerClickForTeleport() { Vector3 clickPosition = GetWorldPositionUnderMouse(); if (clickPosition == Vector3.zero) return; foreach (var marker in markers) { if (marker.bigMapObject == null) continue; float distance = Vector3.Distance( new Vector3(clickPosition.x, 0, clickPosition.z), new Vector3(marker.worldPosition.x, 0, marker.worldPosition.z) ); if (distance <= markerClickTolerance) { RaceMarker raceMarker = marker.bigMapObject.GetComponent<RaceMarker>(); if (raceMarker != null) { raceMarker.TemporaryScaleUp(1.5f, 0.5f); } break; } } } void UpdateDebugInfo() { if (!enableDebug || debugText == null) return; Vector3 worldPos = GetWorldPositionUnderMouse(); debugText.text = $"Мышь: {Input.mousePosition}\n" + $"Мир: {worldPos}\n" + $"Камера: {bigMapCamera.transform.position}\n" + $"Поворот: {bigMapCamera.transform.eulerAngles}\n" + $"Маркеров: {markers.Count}"; if (debugSpherePrefab != null && worldPos != Vector3.zero) { if (Vector3.Distance(worldPos, lastDebugWorldPos) > 1f) { GameObject sphere = Instantiate(debugSpherePrefab, worldPos, Quaternion.identity); sphere.transform.localScale = Vector3.one * 0.5f; Destroy(sphere, 0.3f); lastDebugWorldPos = worldPos; } } } bool IsPointerOverBigMap() { if (bigMapRawImage == null) { return true; } Canvas canvas = bigMapRawImage.canvas; if (canvas == null) { return false; } Camera eventCamera = null; if (canvas.renderMode == RenderMode.ScreenSpaceOverlay) { eventCamera = null; } else if (canvas.renderMode == RenderMode.ScreenSpaceCamera) { eventCamera = canvas.worldCamera; if (eventCamera == null) { eventCamera = Camera.main; } } else if (canvas.renderMode == RenderMode.WorldSpace) { eventCamera = canvas.worldCamera; if (eventCamera == null) { eventCamera = Camera.main; } } Vector2 localPoint; bool success = RectTransformUtility.ScreenPointToLocalPointInRectangle( bigMapRawImage.rectTransform, Input.mousePosition, eventCamera, out localPoint ); if (!success) { return false; } Rect rect = bigMapRawImage.rectTransform.rect; bool isInside = rect.Contains(localPoint); return isInside; } bool IsPointerOverBigMapAlternative() { if (bigMapRawImage == null) return true; GraphicRaycaster raycaster = bigMapRawImage.canvas.GetComponent<GraphicRaycaster>(); if (raycaster == null) { raycaster = bigMapRawImage.canvas.gameObject.AddComponent<GraphicRaycaster>(); } var eventData = new UnityEngine.EventSystems.PointerEventData(UnityEngine.EventSystems.EventSystem.current); eventData.position = Input.mousePosition; var results = new List<UnityEngine.EventSystems.RaycastResult>(); raycaster.Raycast(eventData, results); foreach (var result in results) { if (result.gameObject == bigMapRawImage.gameObject) { return true; } } return false; } void CreateMarkerAtMousePosition() { Vector3 worldPosition = GetWorldPositionUnderMouse(); if (worldPosition != Vector3.zero) { CreateMarker(worldPosition); ShowCreationFeedback(worldPosition); } } Vector3 GetWorldPositionOrthographicTopDown() { Vector3 screenPos = Input.mousePosition; screenPos.z = bigMapCamera.nearClipPlane; Vector3 worldPos = bigMapCamera.ScreenToWorldPoint(screenPos); Ray ray = bigMapCamera.ScreenPointToRay(Input.mousePosition); Plane groundPlane = new Plane(Vector3.up, Vector3.zero); float distance; if (groundPlane.Raycast(ray, out distance)) { Vector3 point = ray.GetPoint(distance); float groundHeight = GetGroundHeight(point); point.y = groundHeight; return point; } worldPos.y = GetGroundHeight(worldPos); return worldPos; } Vector3 GetWorldPositionViaPlane() { Ray ray = bigMapCamera.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if (Physics.Raycast(ray, out hit, Mathf.Infinity, groundLayer)) { return hit.point; } Plane groundPlane = new Plane(Vector3.up, Vector3.zero); float distance; if (groundPlane.Raycast(ray, out distance)) { Vector3 point = ray.GetPoint(distance); point.y = GetGroundHeight(point); return point; } Debug.LogWarning("Не удалось определить позицию мыши!"); return Vector3.zero; } Vector3 GetWorldPositionUnderMouse() { if (bigMapCamera == null || bigMapRawImage == null) { Debug.LogError("Камера или RawImage не назначены!"); return Vector3.zero; } if (bigMapCamera.orthographic && Mathf.Approximately(bigMapCamera.transform.eulerAngles.x, 90f)) { return GetWorldPositionFromRawImage(); } return GetWorldPositionViaRaycast(); } Vector3 GetWorldPositionFromRawImage() { Vector2 localPoint; Camera eventCamera = GetUICamera(); bool success = RectTransformUtility.ScreenPointToLocalPointInRectangle( bigMapRawImage.rectTransform, Input.mousePosition, eventCamera, out localPoint ); if (!success) { Debug.LogWarning("Не удалось получить локальную точку в RawImage"); return Vector3.zero; } Rect rect = bigMapRawImage.rectTransform.rect; float u = (localPoint.x + rect.width / 2) / rect.width; float v = (localPoint.y + rect.height / 2) / rect.height; if (u < 0 || u > 1 || v < 0 || v > 1) { Debug.LogWarning($"Точка вне границ RawImage: u={u:F2}, v={v:F2}"); return Vector3.zero; } return ConvertUVToWorldPosition(u, v); } Vector3 ConvertUVToWorldPosition(float u, float v) { Vector3 cameraPos = bigMapCamera.transform.position; float orthoSize = bigMapCamera.orthographicSize; float aspect = bigMapCamera.aspect; float worldHeight = orthoSize * 2f; float worldWidth = worldHeight * aspect; float relativeX = u - 0.5f; float relativeZ = v - 0.5f; float worldX = cameraPos.x + (relativeX * worldWidth); float worldZ = cameraPos.z + (relativeZ * worldHeight); float groundHeight = GetGroundHeight(new Vector3(worldX, 0, worldZ)); Vector3 worldPos = new Vector3(worldX, groundHeight, worldZ); return worldPos; } Camera GetUICamera() { if (canvas == null && bigMapRawImage != null) { canvas = bigMapRawImage.canvas; } if (canvas != null) { if (canvas.renderMode == RenderMode.ScreenSpaceOverlay) return null; else return canvas.worldCamera ?? Camera.main; } return Camera.main; } Vector3 GetWorldPositionViaRaycast() { Ray ray = bigMapCamera.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if (Physics.Raycast(ray, out hit, Mathf.Infinity, groundLayer)) { return hit.point; } Plane groundPlane = new Plane(Vector3.up, Vector3.zero); float distance; if (groundPlane.Raycast(ray, out distance)) { Vector3 point = ray.GetPoint(distance); point.y = GetGroundHeight(point); return point; } return Vector3.zero; } float GetGroundHeight(Vector3 position) { Vector3 rayStart = new Vector3(position.x, 10000f, position.z); RaycastHit hit; if (Physics.Raycast(rayStart, Vector3.down, out hit, 20000f)) { return hit.point.y; } rayStart = new Vector3(position.x, 5000f, position.z); if (Physics.Raycast(rayStart, Vector3.down, out hit, 10000f)) { return hit.point.y; } rayStart = new Vector3(position.x, -1000f, position.z); if (Physics.Raycast(rayStart, Vector3.up, out hit, 11000f)) { return hit.point.y; } rayStart = new Vector3(position.x, 10000f, position.z); if (Physics.SphereCast(rayStart, 5f, Vector3.down, out hit, 20000f)) { return hit.point.y; } if (Terrain.activeTerrain != null) { float terrainHeight = Terrain.activeTerrain.SampleHeight(new Vector3(position.x, 0, position.z)); if (!float.IsInfinity(terrainHeight)) { return terrainHeight; } } Debug.LogError($"GetGroundHeight: ВСЕ СТРАТЕГИИ ПРОВАЛИЛИСЬ! Нет земли в точке ({position.x}, {position.z})!"); return 0f; } Vector3 GetWorldPositionRaycast() { Vector2 localPoint; Camera eventCamera = uiCamera != null ? uiCamera : Camera.main; if (!RectTransformUtility.ScreenPointToLocalPointInRectangle( bigMapRawImage.rectTransform, Input.mousePosition, eventCamera, out localPoint)) { return Vector3.zero; } Rect rect = bigMapRawImage.rectTransform.rect; Vector2 uv = new Vector2( (localPoint.x - rect.x) / rect.width, (localPoint.y - rect.y) / rect.height ); if (uv.x < 0 || uv.x > 1 || uv.y < 0 || uv.y > 1) return Vector3.zero; Vector3 screenPos = new Vector3(uv.x * Screen.width, uv.y * Screen.height, 0); Ray ray = bigMapCamera.ScreenPointToRay(screenPos); RaycastHit hit; if (Physics.Raycast(ray, out hit, Mathf.Infinity, groundLayer)) { return hit.point; } Plane groundPlane = new Plane(Vector3.up, Vector3.zero); float distance; if (groundPlane.Raycast(ray, out distance)) { Vector3 point = ray.GetPoint(distance); point.y = GetGroundHeight(point); return point; } return Vector3.zero; } void ShowCreationFeedback(Vector3 position) { if (debugSpherePrefab != null) { GameObject sphere = Instantiate(debugSpherePrefab, position, Quaternion.identity); sphere.transform.localScale = Vector3.one * 2f; Renderer renderer = sphere.GetComponent<Renderer>(); if (renderer != null) renderer.material.color = Color.green; Destroy(sphere, 1f); } } void DeleteNearestMarker() { Vector3 mouseWorldPos = GetWorldPositionUnderMouse(); if (mouseWorldPos == Vector3.zero) return; float minDistance = float.MaxValue; int nearestIndex = -1; for (int i = 0; i < markers.Count; i++) { Vector2 markerPos2D = new Vector2(markers[i].worldPosition.x, markers[i].worldPosition.z); Vector2 mousePos2D = new Vector2(mouseWorldPos.x, mouseWorldPos.z); float distance = Vector2.Distance(markerPos2D, mousePos2D); if (distance < minDistance && distance < 15f) { minDistance = distance; nearestIndex = i; } } if (nearestIndex >= 0) { RemoveMarker(nearestIndex); } } public void CreateMarker(Vector3 worldPosition) { MapMarker newMarker = new MapMarker(); newMarker.worldPosition = worldPosition; if (worldMarkerPrefab != null) { float groundHeight = GetGroundHeight(worldPosition); Vector3 worldMarkerPos = new Vector3( worldPosition.x, groundHeight, worldPosition.z ); newMarker.worldObject = Instantiate(worldMarkerPrefab, worldMarkerPos, Quaternion.identity); newMarker.worldObject.name = $"WorldMarker_{markers.Count}"; if (worldMarkerLayerIndex != -1) { SetLayerRecursively(newMarker.worldObject.transform, worldMarkerLayerIndex); } SetupWorldMarker(newMarker.worldObject); } if (miniMapMarkerPrefab != null) { Vector3 miniMapMarkerPos = worldPosition; miniMapMarkerPos.y = miniMapMarkerHeight; newMarker.miniMapObject = Instantiate(miniMapMarkerPrefab, miniMapMarkerPos, Quaternion.Euler(90f, 0f, 0f)); newMarker.miniMapObject.name = $"MiniMapMarker_{markers.Count}"; if (miniMapMarkerLayerIndex != -1) { SetLayerRecursively(newMarker.miniMapObject.transform, miniMapMarkerLayerIndex); } Transform container = GetMiniMapMarkerContainer(); if (container != null) { newMarker.miniMapObject.transform.SetParent(container); } RaceMarker raceMarkerMini = newMarker.miniMapObject.GetComponent<RaceMarker>(); if (raceMarkerMini == null) { raceMarkerMini = newMarker.miniMapObject.AddComponent<RaceMarker>(); } if (miniMapController != null) { miniMapController.RegisterRaceMarker(raceMarkerMini); } } if (bigMapMarkerPrefab != null) { Vector3 bigMapMarkerPos = worldPosition; bigMapMarkerPos.y = bigMapMarkerHeight; newMarker.bigMapObject = Instantiate(bigMapMarkerPrefab, bigMapMarkerPos, Quaternion.Euler(90f, 0f, 0f)); newMarker.bigMapObject.name = $"BigMapMarker_{markers.Count}"; if (bigMapMarkerLayerIndex != -1) { SetLayerRecursively(newMarker.bigMapObject.transform, bigMapMarkerLayerIndex); } Transform bigMapContainer = GetBigMapMarkerContainer(); if (bigMapContainer != null) { newMarker.bigMapObject.transform.SetParent(bigMapContainer); if (newMarker.bigMapObject.transform.parent != bigMapContainer) { Debug.LogError($"Не удалось установить parent для {newMarker.bigMapObject.name}! " + $"Текущий parent: {newMarker.bigMapObject.transform.parent?.name ?? "null"}"); } else { Debug.Log($"Создан маркер #{markers.Count}: {newMarker.bigMapObject.name} " + $"в контейнере {bigMapContainer.name}, всего детей: {bigMapContainer.childCount}"); } } else { Debug.LogError("BigMap контейнер НЕ НАЙДЕН!"); return; } RaceMarker raceMarkerBig = newMarker.bigMapObject.GetComponent<RaceMarker>(); if (raceMarkerBig == null) { raceMarkerBig = newMarker.bigMapObject.AddComponent<RaceMarker>(); } raceMarkerBig.SetBigMapMarkerVisible(true); if (bigMapController != null) { bigMapController.RegisterRaceMarker(raceMarkerBig); StartCoroutine(DelayedBigMapRegistration(raceMarkerBig)); } else { bigMapController = FindFirstObjectByType<BigMapController>(); if (bigMapController != null) { bigMapController.RegisterRaceMarker(raceMarkerBig); StartCoroutine(DelayedBigMapRegistration(raceMarkerBig)); } else { Debug.LogWarning($"BigMapController не найден для маркера #{markers.Count}"); StartCoroutine(FindAndRegisterLater(raceMarkerBig)); } } } markers.Add(newMarker); LinkMarkersWithTrigger(newMarker, markers.Count - 1); RegisterMarkerInTeleporter(newMarker); } IEnumerator DelayedBigMapRegistration(RaceMarker marker) { yield return new WaitForSeconds(0.2f); if (marker == null) yield break; if (bigMapController == null) bigMapController = FindFirstObjectByType<BigMapController>(); if (bigMapController != null) { var markers = bigMapController.GetType() .GetField("raceMarkers", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance) ?.GetValue(bigMapController) as List<RaceMarker>; if (markers != null && !markers.Contains(marker)) { bigMapController.RegisterRaceMarker(marker); } } } IEnumerator FindAndRegisterLater(RaceMarker marker) { yield return new WaitForSeconds(0.5f); if (marker == null) yield break; var bigMap = FindFirstObjectByType<BigMapController>(); if (bigMap != null) { bigMap.RegisterRaceMarker(marker); } } private IEnumerator RegisterMarkerDelayed(RaceMarker marker) { yield return new WaitForSeconds(0.5f); if (bigMapController == null) { bigMapController = FindFirstObjectByType<BigMapController>(); } if (bigMapController != null && marker != null) { bigMapController.RegisterRaceMarker(marker); } } void RegisterMarkerInTeleporter(MapMarker marker) { if (marker.worldObject != null) { RaceMarker raceMarker = marker.worldObject.GetComponent<RaceMarker>(); if (raceMarker == null) { raceMarker = marker.worldObject.AddComponent<RaceMarker>(); } RaceMarkerTeleporter teleporter = FindFirstObjectByType<RaceMarkerTeleporter>(); if (teleporter != null) { teleporter.RegisterMarker(raceMarker); } } } public void RemoveMarkerByGameObject(GameObject worldMarkerObject) { int indexToRemove = -1; for (int i = 0; i < markers.Count; i++) { if (markers[i].worldObject == worldMarkerObject) { indexToRemove = i; break; } } if (indexToRemove >= 0) { RemoveMarker(indexToRemove); } else { Debug.LogWarning($"Не найден маркер для удаления: {worldMarkerObject.name}"); } } void LinkMarkersWithTrigger(MapMarker marker, int index) { if (marker.worldObject != null) { WorldMarkerCollision trigger = marker.worldObject.GetComponent<WorldMarkerCollision>(); if (trigger == null) { trigger = marker.worldObject.AddComponent<WorldMarkerCollision>(); } trigger.Initialize(this, marker.miniMapObject, marker.bigMapObject); } } public void RemoveMarker(int index) { if (index < 0 || index >= markers.Count) { Debug.LogWarning($"Попытка удалить несуществующий маркер с индексом {index}"); return; } MapMarker marker = markers[index]; if (marker.worldObject != null) { Destroy(marker.worldObject); } if (marker.miniMapObject != null) { Destroy(marker.miniMapObject); } if (marker.bigMapObject != null) { Destroy(marker.bigMapObject); } markers.RemoveAt(index); } void SetupWorldMarker(GameObject marker) { Light light = marker.GetComponentInChildren<Light>(); } void UpdateMiniMapMarkerPosition(MapMarker marker) { if (marker.miniMapObject == null) return; Vector3 pos = marker.worldPosition; pos.y = miniMapMarkerHeight; marker.miniMapObject.transform.position = pos; marker.miniMapObject.transform.rotation = Quaternion.Euler(90f, 0f, 0f); marker.miniMapObject.transform.localScale = Vector3.one * 12f; } void UpdateBigMapMarkerPosition(MapMarker marker) { if (marker.bigMapObject == null) return; Vector3 pos = marker.worldPosition; pos.y = bigMapMarkerHeight; marker.bigMapObject.transform.position = pos; marker.bigMapObject.transform.rotation = Quaternion.Euler(90f, 0f, 0f); } private void SetLayerRecursively(Transform obj, int layerIndex) { obj.gameObject.layer = layerIndex; foreach (Transform child in obj) { SetLayerRecursively(child, layerIndex); } } Transform GetMiniMapMarkerContainer() { return MarkerContainersManager.Instance.GetMiniMapMarkersContainer(); } Transform GetBigMapMarkerContainer() { return MarkerContainersManager.Instance.GetBigMapMarkersContainer(); } void LateUpdate() { UpdateMarkersPosition(); UpdateBigMapMarkersScale(); if (enableDebug && Time.frameCount % 60 == 0) { Transform container = GetBigMapMarkerContainer(); if (container != null) { int childCount = container.childCount; } } } void UpdateMarkersPosition() { foreach (var marker in markers) { if (marker.miniMapObject != null) UpdateMiniMapMarkerPosition(marker); if (marker.bigMapObject != null) UpdateBigMapMarkerPosition(marker); } } void UpdateBigMapMarkersScale() { if (bigMapController == null) { bigMapController = FindFirstObjectByType<BigMapController>(); } float currentScale; if (bigMapController != null) { currentScale = bigMapController.CurrentArrowScale; } else { currentScale = defaultBigMapMarkerScale; } float markerScale = currentScale * markerScaleMultiplier; if (markerScale < 0.5f) { markerScale = 1.5f; Debug.LogWarning($"Масштаб маркера слишком мал ({markerScale}), установлен минимальный 1.5"); } foreach (var marker in markers) { if (marker.bigMapObject != null) { marker.bigMapObject.transform.localScale = Vector3.one * markerScale; } } } [ContextMenu("Принудительно обновить масштаб маркеров")] public void ForceUpdateMarkersScale() { UpdateBigMapMarkersScale(); } public void ClearAllMarkers() { foreach (var marker in markers) { if (marker.worldObject != null) Destroy(marker.worldObject); if (marker.miniMapObject != null) Destroy(marker.miniMapObject); if (marker.bigMapObject != null) Destroy(marker.bigMapObject); } markers.Clear(); } [ContextMenu("Тест: Создать маркер в центре камеры")] public void TestCreateMarkerAtCameraCenter() { Vector3 cameraPos = bigMapCamera.transform.position; Vector3 groundPos = new Vector3(cameraPos.x, GetGroundHeight(cameraPos), cameraPos.z); CreateMarker(groundPos); } [ContextMenu("Тест: Создать маркеры по углам видимой области")] public void TestCreateCornerMarkers() { ClearAllMarkers(); if (bigMapCamera == null || !bigMapCamera.orthographic) return; Vector3 cameraPos = bigMapCamera.transform.position; float orthoSize = bigMapCamera.orthographicSize; float aspect = bigMapCamera.aspect; float worldHeight = orthoSize * 2f; float worldWidth = worldHeight * aspect; Vector3[] corners = new Vector3[] { new Vector3(cameraPos.x - worldWidth/2, 0, cameraPos.z - worldHeight/2), new Vector3(cameraPos.x + worldWidth/2, 0, cameraPos.z - worldHeight/2), new Vector3(cameraPos.x - worldWidth/2, 0, cameraPos.z + worldHeight/2), new Vector3(cameraPos.x + worldWidth/2, 0, cameraPos.z + worldHeight/2) }; foreach (Vector3 corner in corners) { Vector3 pos = corner; pos.y = GetGroundHeight(pos); CreateMarker(pos); } Vector3 center = new Vector3(cameraPos.x, GetGroundHeight(cameraPos), cameraPos.z); CreateMarker(center); } [ContextMenu("Тест: Вывести информацию о камере")] public void DebugCameraInfo() { if (bigMapCamera == null) return; if (bigMapCamera.orthographic) { float height = bigMapCamera.orthographicSize * 2; float width = height * bigMapCamera.aspect; Vector3 center = bigMapCamera.transform.position; } } void OnDrawGizmosSelected() { if (!enableDebug || bigMapCamera == null) return; if (bigMapCamera.orthographic) { Gizmos.color = Color.yellow; Vector3 cameraPos = bigMapCamera.transform.position; float orthoSize = bigMapCamera.orthographicSize; float aspect = bigMapCamera.aspect; float height = orthoSize * 2; float width = height * aspect; Vector3[] corners = new Vector3[4]; corners[0] = new Vector3(cameraPos.x - width / 2, cameraPos.y - 10, cameraPos.z - height / 2); corners[1] = new Vector3(cameraPos.x + width / 2, cameraPos.y - 10, cameraPos.z - height / 2); corners[2] = new Vector3(cameraPos.x + width / 2, cameraPos.y - 10, cameraPos.z + height / 2); corners[3] = new Vector3(cameraPos.x - width / 2, cameraPos.y - 10, cameraPos.z + height / 2); for (int i = 0; i < 4; i++) { Gizmos.DrawLine(corners[i], corners[(i + 1) % 4]); } Gizmos.color = Color.red; Gizmos.DrawSphere(new Vector3(cameraPos.x, GetGroundHeight(cameraPos), cameraPos.z), 2f); } } MapMarker GetMarkerAtPosition(Vector3 position) { foreach (var marker in markers) { Vector2 markerPos2D = new Vector2(marker.worldPosition.x, marker.worldPosition.z); Vector2 clickPos2D = new Vector2(position.x, position.z); float distance = Vector2.Distance(markerPos2D, clickPos2D); if (distance <= markerClickTolerance) { return marker; } } return null; } void ShowDeletionFeedback(Vector3 position) { if (debugSpherePrefab != null) { GameObject sphere = Instantiate(debugSpherePrefab, position, Quaternion.identity); sphere.transform.localScale = Vector3.one * 3f; Renderer renderer = sphere.GetComponent<Renderer>(); if (renderer != null) renderer.material.color = Color.red; Destroy(sphere, 1f); } } public List<MapMarker> GetAllMarkers() { return markers; } [ContextMenu("Тест: Показать границы RawImage")] public void DebugRawImageBounds() { if (bigMapRawImage == null) { Debug.LogError("RawImage не назначен"); return; } RectTransform rect = bigMapRawImage.rectTransform; Vector3[] corners = new Vector3[4]; rect.GetWorldCorners(corners); } [ContextMenu("Тест: Показать параметры камеры")] public void DebugCameraParameters() { if (bigMapCamera == null) { Debug.LogError("Камера не назначена"); return; } float height = bigMapCamera.orthographicSize * 2; float width = height * bigMapCamera.aspect; Vector3 center = bigMapCamera.transform.position; } public float GetCurrentMarkerScale() { if (bigMapController == null) return 1f; return bigMapController.CurrentArrowScale * markerScaleMultiplier; } }