전장의 안개 구현
This commit is contained in:
186
Assets/Scripts/FogOfWarRenderer.cs
Normal file
186
Assets/Scripts/FogOfWarRenderer.cs
Normal file
@@ -0,0 +1,186 @@
|
||||
using Unity.Netcode;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Northbound
|
||||
{
|
||||
/// <summary>
|
||||
/// 전장의 안개 시각적 렌더링 (클라이언트)
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
|
||||
public class FogOfWarRenderer : MonoBehaviour
|
||||
{
|
||||
[Header("Settings")]
|
||||
public Material fogMaterial;
|
||||
public float updateInterval = 0.1f;
|
||||
public float fogHeight = 5f; // 안개 높이 (지형보다 약간 위)
|
||||
|
||||
[Header("Colors")]
|
||||
public Color unexploredColor = new Color(0, 0, 0, 1f); // 완전히 어두움
|
||||
public Color exploredColor = new Color(0, 0, 0, 0.6f); // 반투명
|
||||
public Color visibleColor = new Color(0, 0, 0, 0f); // 투명
|
||||
|
||||
private Texture2D _fogTexture;
|
||||
private Color[] _colors;
|
||||
private MeshRenderer _meshRenderer;
|
||||
private float _updateTimer;
|
||||
private ulong _localClientId;
|
||||
private bool _isInitialized;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// NetworkManager 준비 대기
|
||||
if (NetworkManager.Singleton == null || !NetworkManager.Singleton.IsClient)
|
||||
{
|
||||
Debug.LogWarning("[FogOfWar] NetworkManager가 준비되지 않았습니다. 대기 중...");
|
||||
return;
|
||||
}
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
if (_isInitialized) return;
|
||||
|
||||
_localClientId = NetworkManager.Singleton.LocalClientId;
|
||||
|
||||
var fogSystem = FogOfWarSystem.Instance;
|
||||
if (fogSystem == null)
|
||||
{
|
||||
Debug.LogError("[FogOfWar] FogOfWarSystem을 찾을 수 없습니다! 씬에 FogOfWarSystem GameObject가 있는지 확인하세요.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 텍스처 생성
|
||||
_fogTexture = new Texture2D(fogSystem.gridWidth, fogSystem.gridHeight)
|
||||
{
|
||||
filterMode = FilterMode.Bilinear,
|
||||
wrapMode = TextureWrapMode.Clamp
|
||||
};
|
||||
_colors = new Color[fogSystem.gridWidth * fogSystem.gridHeight];
|
||||
|
||||
// 초기 색상을 미탐색 상태로 설정
|
||||
for (int i = 0; i < _colors.Length; i++)
|
||||
{
|
||||
_colors[i] = unexploredColor;
|
||||
}
|
||||
_fogTexture.SetPixels(_colors);
|
||||
_fogTexture.Apply();
|
||||
|
||||
// 머티리얼 설정
|
||||
_meshRenderer = GetComponent<MeshRenderer>();
|
||||
if (fogMaterial != null)
|
||||
{
|
||||
Material instanceMaterial = new Material(fogMaterial);
|
||||
instanceMaterial.mainTexture = _fogTexture;
|
||||
_meshRenderer.material = instanceMaterial;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("[FogOfWar] Fog Material이 설정되지 않았습니다!");
|
||||
}
|
||||
|
||||
// 렌더링 레이어 설정
|
||||
gameObject.layer = LayerMask.NameToLayer("UI"); // 또는 별도 레이어 생성
|
||||
|
||||
// 메쉬 생성
|
||||
CreatePlaneMesh(fogSystem);
|
||||
|
||||
_isInitialized = true;
|
||||
Debug.Log($"<color=cyan>[FogOfWar] 렌더러 초기화 완료 (Client {_localClientId})</color>");
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
// NetworkManager가 준비되지 않았다면 초기화 시도
|
||||
if (!_isInitialized && NetworkManager.Singleton != null && NetworkManager.Singleton.IsClient)
|
||||
{
|
||||
Initialize();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_isInitialized) return;
|
||||
|
||||
_updateTimer += Time.deltaTime;
|
||||
if (_updateTimer >= updateInterval)
|
||||
{
|
||||
_updateTimer = 0f;
|
||||
UpdateFogTexture();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateFogTexture()
|
||||
{
|
||||
var fogSystem = FogOfWarSystem.Instance;
|
||||
if (fogSystem == null) return;
|
||||
|
||||
var fogData = fogSystem.GetPlayerFogData(_localClientId);
|
||||
|
||||
for (int y = 0; y < fogSystem.gridHeight; y++)
|
||||
{
|
||||
for (int x = 0; x < fogSystem.gridWidth; x++)
|
||||
{
|
||||
FogOfWarState state = fogData.GetState(x, y);
|
||||
int index = y * fogSystem.gridWidth + x;
|
||||
|
||||
_colors[index] = state switch
|
||||
{
|
||||
FogOfWarState.Visible => visibleColor,
|
||||
FogOfWarState.Explored => exploredColor,
|
||||
FogOfWarState.Unexplored => unexploredColor,
|
||||
_ => unexploredColor
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
_fogTexture.SetPixels(_colors);
|
||||
_fogTexture.Apply();
|
||||
}
|
||||
|
||||
private void CreatePlaneMesh(FogOfWarSystem fogSystem)
|
||||
{
|
||||
MeshFilter meshFilter = GetComponent<MeshFilter>();
|
||||
|
||||
float width = fogSystem.gridWidth * fogSystem.cellSize;
|
||||
float height = fogSystem.gridHeight * fogSystem.cellSize;
|
||||
|
||||
Mesh mesh = new Mesh
|
||||
{
|
||||
name = "FogOfWar Plane"
|
||||
};
|
||||
|
||||
mesh.vertices = new Vector3[]
|
||||
{
|
||||
new Vector3(0, fogHeight, 0),
|
||||
new Vector3(width, fogHeight, 0),
|
||||
new Vector3(0, fogHeight, height),
|
||||
new Vector3(width, fogHeight, height)
|
||||
};
|
||||
|
||||
mesh.triangles = new int[] { 0, 2, 1, 2, 3, 1 };
|
||||
|
||||
mesh.uv = new Vector2[]
|
||||
{
|
||||
new Vector2(0, 0),
|
||||
new Vector2(1, 0),
|
||||
new Vector2(0, 1),
|
||||
new Vector2(1, 1)
|
||||
};
|
||||
|
||||
mesh.RecalculateNormals();
|
||||
|
||||
meshFilter.mesh = mesh;
|
||||
transform.position = fogSystem.worldOrigin;
|
||||
|
||||
Debug.Log($"<color=cyan>[FogOfWar] Plane Mesh 생성 완료: {width}x{height} at {fogSystem.worldOrigin}</color>");
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (_fogTexture != null)
|
||||
{
|
||||
Destroy(_fogTexture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user