2026-04-03 미니맵 추가중
This commit is contained in:
BIN
Assets/01_Scenes/GameScene.unity
LFS
BIN
Assets/01_Scenes/GameScene.unity
LFS
Binary file not shown.
137
Assets/02_Scripts/Managers/Local/MinimapManager.cs
Normal file
137
Assets/02_Scripts/Managers/Local/MinimapManager.cs
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Canvas (기존 InGameUI Canvas)
|
||||||
|
└── MinimapRoot (빈 오브젝트, MinimapManager 컴포넌트 부착)
|
||||||
|
├── MapMask (원형/사각형 마스크, Mask 컴포넌트)
|
||||||
|
│ ├── MapImage (RawImage) ← _mapImage, _mapRect
|
||||||
|
│ ├── PlayerIcon (Image) ← _playerIcon
|
||||||
|
│ └── MarkerContainer (빈 오브젝트) ← _markerContainer
|
||||||
|
└── MinimapFrame (Image) ← 테두리 장식 (선택)
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class MinimapManager : MonoBehaviour
|
||||||
|
{
|
||||||
|
[Header("미니맵 UI")]
|
||||||
|
[SerializeField] private RawImage _mapImage; // 맵 배경 (RenderTexture 또는 프리렌더 이미지)
|
||||||
|
[SerializeField] private RectTransform _mapRect; // 맵 이미지의 RectTransform
|
||||||
|
[SerializeField] private RectTransform _playerIcon; // 플레이어 아이콘
|
||||||
|
[SerializeField] private RectTransform _markerContainer;// 마커 부모
|
||||||
|
|
||||||
|
[Header("프리렌더 이미지")]
|
||||||
|
[SerializeField] private Texture2D _bakedMapImage;
|
||||||
|
|
||||||
|
[Header("월드 범위")]
|
||||||
|
[SerializeField] private Vector2 _worldMin = new Vector2(-50, -50);
|
||||||
|
[SerializeField] private Vector2 _worldMax = new Vector2(50, 50);
|
||||||
|
|
||||||
|
[Header("모드")]
|
||||||
|
[SerializeField] private bool _useRenderTexture = true; // true: 실시간(개발용), false: 프리렌더(출시용)
|
||||||
|
|
||||||
|
//개발용 설정
|
||||||
|
//----------------------------------------------------------
|
||||||
|
[Header("미니맵 카메라")]
|
||||||
|
[SerializeField] private Camera _minimapCamera;
|
||||||
|
[SerializeField] private RenderTexture _renderTexture;
|
||||||
|
|
||||||
|
[Header("카메라 설정")]
|
||||||
|
[SerializeField] private float _cameraHeight = 50f;
|
||||||
|
[SerializeField] private float _zoomLevel = 30f;
|
||||||
|
[SerializeField] private float _minZoom = 15f;
|
||||||
|
[SerializeField] private float _maxZoom = 80f;
|
||||||
|
//----------------------------------------------------------
|
||||||
|
|
||||||
|
private List<MinimapMarker> _markers = new List<MinimapMarker>();
|
||||||
|
|
||||||
|
private void Start()
|
||||||
|
{
|
||||||
|
ApplyMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LateUpdate()
|
||||||
|
{
|
||||||
|
UpdateCamera();
|
||||||
|
UpdatePlayerIcon();
|
||||||
|
UpdateMarkers();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ApplyMode()
|
||||||
|
{
|
||||||
|
if (_useRenderTexture)
|
||||||
|
{
|
||||||
|
_mapImage.texture = _renderTexture;
|
||||||
|
if (_minimapCamera != null) _minimapCamera.gameObject.SetActive(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_mapImage.texture = _bakedMapImage;
|
||||||
|
if (_minimapCamera != null) _minimapCamera.gameObject.SetActive(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateCamera()
|
||||||
|
{
|
||||||
|
if (!_useRenderTexture || _minimapCamera == null) return;
|
||||||
|
|
||||||
|
Vector3 pos = GameManager.Instance.Level.CurrentCharacter.transform.position;
|
||||||
|
_minimapCamera.transform.position = new Vector3(pos.x, pos.y + _cameraHeight, pos.z);
|
||||||
|
_minimapCamera.orthographicSize = _zoomLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdatePlayerIcon()
|
||||||
|
{
|
||||||
|
if (_playerIcon == null) return;
|
||||||
|
|
||||||
|
_playerIcon.anchoredPosition = WorldToMapPos(GameManager.Instance.Level.CurrentCharacter.transform.position);
|
||||||
|
_playerIcon.localRotation = Quaternion.Euler(0, 0, -GameManager.Instance.Level.CurrentCharacter.transform.eulerAngles.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateMarkers()
|
||||||
|
{
|
||||||
|
for (int i = _markers.Count - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if (_markers[i] == null)
|
||||||
|
{
|
||||||
|
_markers.RemoveAt(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
_markers[i].UpdatePosition(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2 WorldToMapPos(Vector3 worldPos)
|
||||||
|
{
|
||||||
|
float ratioX = (worldPos.x - _worldMin.x) / (_worldMax.x - _worldMin.x);
|
||||||
|
float ratioY = (worldPos.z - _worldMin.y) / (_worldMax.y - _worldMin.y);
|
||||||
|
|
||||||
|
//sizeDelta는 앵커 영역과 실제 UI 크기의 차이값
|
||||||
|
return new Vector2(
|
||||||
|
ratioX * _mapRect.sizeDelta.x - _mapRect.sizeDelta.x * 0.5f,
|
||||||
|
ratioY * _mapRect.sizeDelta.y - _mapRect.sizeDelta.y * 0.5f
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RectTransform MarkerContainer => _markerContainer;
|
||||||
|
|
||||||
|
public void RegisterMarker(MinimapMarker marker)
|
||||||
|
{
|
||||||
|
if (!_markers.Contains(marker))
|
||||||
|
_markers.Add(marker);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnregisterMarker(MinimapMarker marker)
|
||||||
|
{
|
||||||
|
_markers.Remove(marker);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetZoom(float zoom)
|
||||||
|
{
|
||||||
|
_zoomLevel = Mathf.Clamp(zoom, _minZoom, _maxZoom);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ZoomIn(float amount) => SetZoom(_zoomLevel - amount);
|
||||||
|
public void ZoomOut(float amount) => SetZoom(_zoomLevel + amount);
|
||||||
|
}
|
||||||
2
Assets/02_Scripts/Managers/Local/MinimapManager.cs.meta
Normal file
2
Assets/02_Scripts/Managers/Local/MinimapManager.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0298fb5f6cff794429c87fab23351ae8
|
||||||
8
Assets/02_Scripts/UI/Minimap.meta
Normal file
8
Assets/02_Scripts/UI/Minimap.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 6ac2fd73b3fec65448b65adadd35989f
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
40
Assets/02_Scripts/UI/Minimap/MinimapCapture.cs
Normal file
40
Assets/02_Scripts/UI/Minimap/MinimapCapture.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#if UNITY_EDITOR
|
||||||
|
using UnityEditor;
|
||||||
|
#endif
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public class MinimapCapture : MonoBehaviour
|
||||||
|
{
|
||||||
|
[SerializeField] private Camera _minimapCamera;
|
||||||
|
[SerializeField] private int _resolution = 1024;
|
||||||
|
[SerializeField] private string _savePath = "Assets/08_UI/MinimapImage.png";
|
||||||
|
|
||||||
|
[ContextMenu("미니맵 이미지 캡처")]
|
||||||
|
public void CaptureMapImage()
|
||||||
|
{
|
||||||
|
RenderTexture rt = new RenderTexture(_resolution, _resolution, 24);
|
||||||
|
_minimapCamera.targetTexture = rt;
|
||||||
|
_minimapCamera.Render();
|
||||||
|
|
||||||
|
RenderTexture.active = rt;
|
||||||
|
Texture2D tex = new Texture2D(_resolution, _resolution, TextureFormat.RGB24, false);
|
||||||
|
tex.ReadPixels(new Rect(0, 0, _resolution, _resolution), 0, 0);
|
||||||
|
tex.Apply();
|
||||||
|
|
||||||
|
byte[] bytes = tex.EncodeToPNG();
|
||||||
|
System.IO.File.WriteAllBytes(_savePath, bytes);
|
||||||
|
|
||||||
|
_minimapCamera.targetTexture = null;
|
||||||
|
RenderTexture.active = null;
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
DestroyImmediate(rt);
|
||||||
|
DestroyImmediate(tex);
|
||||||
|
AssetDatabase.Refresh();
|
||||||
|
Debug.Log($"미니맵 이미지 저장 완료: {_savePath}");
|
||||||
|
#else
|
||||||
|
Destroy(rt);
|
||||||
|
Destroy(tex);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
2
Assets/02_Scripts/UI/Minimap/MinimapCapture.cs.meta
Normal file
2
Assets/02_Scripts/UI/Minimap/MinimapCapture.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d4a6e37a841f8f64bb2142ceb2c29d0e
|
||||||
52
Assets/02_Scripts/UI/Minimap/MinimapMarker.cs
Normal file
52
Assets/02_Scripts/UI/Minimap/MinimapMarker.cs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
|
public class MinimapMarker : MonoBehaviour
|
||||||
|
{
|
||||||
|
[SerializeField] private Sprite _iconSprite;
|
||||||
|
[SerializeField] private Color _iconColor = Color.red;
|
||||||
|
[SerializeField] private Vector2 _iconSize = new Vector2(10f, 10f);
|
||||||
|
[SerializeField] private bool _rotateWithTarget = false;
|
||||||
|
|
||||||
|
private RectTransform _iconRect;
|
||||||
|
private Transform _target; // 추적할 월드 오브젝트
|
||||||
|
|
||||||
|
private void Awake()
|
||||||
|
{
|
||||||
|
_target = transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Initialize(MinimapManager manager)
|
||||||
|
{
|
||||||
|
// 마커 아이콘 UI 생성
|
||||||
|
GameObject iconObj = new GameObject($"Marker_{gameObject.name}");
|
||||||
|
iconObj.transform.SetParent(manager.MarkerContainer, false);
|
||||||
|
|
||||||
|
Image img = iconObj.AddComponent<Image>();
|
||||||
|
img.sprite = _iconSprite;
|
||||||
|
img.color = _iconColor;
|
||||||
|
|
||||||
|
_iconRect = iconObj.GetComponent<RectTransform>();
|
||||||
|
_iconRect.sizeDelta = _iconSize;
|
||||||
|
|
||||||
|
manager.RegisterMarker(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdatePosition(MinimapManager manager)
|
||||||
|
{
|
||||||
|
if (_iconRect == null || _target == null) return;
|
||||||
|
|
||||||
|
_iconRect.anchoredPosition = manager.WorldToMapPos(_target.position);
|
||||||
|
|
||||||
|
if (_rotateWithTarget)
|
||||||
|
{
|
||||||
|
_iconRect.localRotation = Quaternion.Euler(0, 0, -_target.eulerAngles.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDestroy()
|
||||||
|
{
|
||||||
|
if (_iconRect != null)
|
||||||
|
Destroy(_iconRect.gameObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
2
Assets/02_Scripts/UI/Minimap/MinimapMarker.cs.meta
Normal file
2
Assets/02_Scripts/UI/Minimap/MinimapMarker.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 85b8750f387527d4c8751eefec4c4c47
|
||||||
Reference in New Issue
Block a user