기본 배치 건물이 시야를 제공하도록 변경
This commit is contained in:
@@ -6,8 +6,16 @@ namespace Northbound
|
||||
/// <summary>
|
||||
/// 블랙스미스 건물 - 업그레이드 구매 가능
|
||||
/// </summary>
|
||||
public class Blacksmith : MonoBehaviour, IInteractable
|
||||
public class Blacksmith : NetworkBehaviour, IInteractable, IVisionProvider, ITeamMember
|
||||
{
|
||||
[Header("Vision Settings")]
|
||||
[Tooltip("블랙스미스가 제공하는 시야 범위")]
|
||||
public float visionRange = 10f;
|
||||
|
||||
[Header("Team")]
|
||||
[Tooltip("건물의 팀")]
|
||||
public TeamType initialTeam = TeamType.Player;
|
||||
|
||||
[Header("UI Reference")]
|
||||
[SerializeField] private GameObject _upgradePopupPrefab;
|
||||
|
||||
@@ -55,9 +63,6 @@ namespace Northbound
|
||||
return transform;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
private void OpenUpgradePopup(ulong playerId)
|
||||
@@ -115,12 +120,63 @@ namespace Northbound
|
||||
return null;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
public override void OnDestroy()
|
||||
{
|
||||
if (_popupInstance != null)
|
||||
{
|
||||
Destroy(_popupInstance);
|
||||
}
|
||||
base.OnDestroy();
|
||||
}
|
||||
|
||||
#region NetworkBehaviour Overrides
|
||||
|
||||
public override void OnNetworkSpawn()
|
||||
{
|
||||
if (IsServer)
|
||||
{
|
||||
// 시야 제공자로 등록
|
||||
FogOfWarSystem.Instance?.RegisterVisionProvider(this);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnNetworkDespawn()
|
||||
{
|
||||
if (IsServer)
|
||||
{
|
||||
// 시야 제공자 등록 해제
|
||||
FogOfWarSystem.Instance?.UnregisterVisionProvider(this);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IVisionProvider Implementation
|
||||
|
||||
public ulong GetOwnerId() => 0; // 블랙스미스는 모든 플레이어에게 시야 제공
|
||||
|
||||
public float GetVisionRange() => visionRange;
|
||||
|
||||
Transform IVisionProvider.GetTransform() => transform;
|
||||
|
||||
public bool IsActive() => IsSpawned;
|
||||
|
||||
TeamType IVisionProvider.GetTeam() => initialTeam;
|
||||
|
||||
#endregion
|
||||
|
||||
#region ITeamMember Implementation
|
||||
|
||||
public TeamType GetTeam() => initialTeam;
|
||||
|
||||
public bool IsDead() => false; // 블랙스미스는 파괴되지 않음
|
||||
|
||||
public void SetTeam(TeamType team)
|
||||
{
|
||||
// 블랙스미스의 팀은 변경할 수 없음
|
||||
Debug.LogWarning("[Blacksmith] 블랙스미스의 팀은 변경할 수 없습니다.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,12 +7,15 @@ namespace Northbound
|
||||
/// <summary>
|
||||
/// 플레이어가 자원을 건내받아 게임의 전역 자원으로 관리하는 중앙 허브
|
||||
/// </summary>
|
||||
public class Core : NetworkBehaviour, IInteractable, IDamageable, ITeamMember
|
||||
public class Core : NetworkBehaviour, IInteractable, IDamageable, ITeamMember, IVisionProvider
|
||||
{
|
||||
[Header("Core Settings")]
|
||||
public int maxStorageCapacity = 1000; // 코어의 최대 저장 용량
|
||||
public bool unlimitedStorage = false; // 무제한 저장소
|
||||
|
||||
[Header("Vision")]
|
||||
public float visionRange = 15f; // 코어가 제공하는 시야 범위
|
||||
|
||||
[Header("Health")]
|
||||
public int maxHealth = 1000;
|
||||
public GameObject damageEffectPrefab;
|
||||
@@ -55,6 +58,9 @@ namespace Northbound
|
||||
{
|
||||
_totalResources.Value = 0;
|
||||
_currentHealth.Value = maxHealth;
|
||||
|
||||
// 시야 제공자로 등록
|
||||
FogOfWarSystem.Instance?.RegisterVisionProvider(this);
|
||||
}
|
||||
|
||||
_currentHealth.OnValueChanged += OnHealthChanged;
|
||||
@@ -62,6 +68,12 @@ namespace Northbound
|
||||
|
||||
public override void OnNetworkDespawn()
|
||||
{
|
||||
if (IsServer)
|
||||
{
|
||||
// 시야 제공자 등록 해제
|
||||
FogOfWarSystem.Instance?.UnregisterVisionProvider(this);
|
||||
}
|
||||
|
||||
_currentHealth.OnValueChanged -= OnHealthChanged;
|
||||
}
|
||||
|
||||
@@ -372,5 +384,19 @@ namespace Northbound
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IVisionProvider Implementation
|
||||
|
||||
public ulong GetOwnerId() => 0; // 코어는 모든 플레이어에게 시야 제공
|
||||
|
||||
public float GetVisionRange() => visionRange;
|
||||
|
||||
Transform IVisionProvider.GetTransform() => transform;
|
||||
|
||||
public bool IsActive() => IsSpawned && !IsDead();
|
||||
|
||||
TeamType IVisionProvider.GetTeam() => TeamType.Player;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -182,17 +182,39 @@ namespace Northbound
|
||||
{
|
||||
if (NetworkManager.Singleton == null) return ulong.MaxValue;
|
||||
|
||||
var localPlayer = NetworkManager.Singleton.SpawnManager.GetLocalPlayerObject();
|
||||
if (localPlayer != null)
|
||||
// 방법 1: SpawnManager에서 찾기
|
||||
NetworkObject localPlayer = null;
|
||||
if (NetworkManager.Singleton.SpawnManager != null)
|
||||
{
|
||||
var playerController = localPlayer.GetComponent<NetworkPlayerController>();
|
||||
if (playerController != null)
|
||||
localPlayer = NetworkManager.Singleton.SpawnManager.GetLocalPlayerObject();
|
||||
}
|
||||
|
||||
// 방법 2: LocalClient에서 찾기
|
||||
if (localPlayer == null && NetworkManager.Singleton.LocalClient != null)
|
||||
{
|
||||
localPlayer = NetworkManager.Singleton.LocalClient.PlayerObject;
|
||||
}
|
||||
|
||||
// 방법 3: 직접 검색 (IsLocalPlayer인 플레이어 찾기)
|
||||
if (localPlayer == null)
|
||||
{
|
||||
var allPlayers = FindObjectsByType<NetworkPlayerController>(FindObjectsSortMode.None);
|
||||
foreach (var player in allPlayers)
|
||||
{
|
||||
return playerController.OwnerPlayerId;
|
||||
if (player.IsLocalPlayer)
|
||||
{
|
||||
localPlayer = player.GetComponent<NetworkObject>();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ulong.MaxValue;
|
||||
if (localPlayer == null) return ulong.MaxValue;
|
||||
|
||||
var playerController = localPlayer.GetComponent<NetworkPlayerController>();
|
||||
if (playerController == null) return ulong.MaxValue;
|
||||
|
||||
return playerController.OwnerPlayerId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -307,7 +307,8 @@ namespace Northbound
|
||||
if (!_visionProviders.Contains(provider))
|
||||
{
|
||||
_visionProviders.Add(provider);
|
||||
// Debug.Log($"<color=cyan>[FogOfWar] Vision Provider 등록: {provider.GetTransform().name} (Owner: {provider.GetOwnerId()})</color>");
|
||||
// 즉시 시야 업데이트 트리거
|
||||
_updateTimer = updateInterval;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,9 @@ namespace Northbound
|
||||
public class FogOfWarVisibility : MonoBehaviour
|
||||
{
|
||||
[Header("Visibility Settings")]
|
||||
[Tooltip("Always show this object regardless of fog state (for core, important structures)")]
|
||||
public bool alwaysVisible = false;
|
||||
|
||||
[Tooltip("Show this object in explored areas (greyed out) or only when visible")]
|
||||
public bool showInExploredAreas = false;
|
||||
|
||||
@@ -19,10 +22,13 @@ namespace Northbound
|
||||
[Tooltip("Renderers to show/hide (auto-detected if empty)")]
|
||||
public Renderer[] renderers;
|
||||
|
||||
[Header("Height-Based Distant Visibility")]
|
||||
[Header("Extended Visibility")]
|
||||
[Tooltip("Enable visibility from farther away based on object height")]
|
||||
public bool enableDistantVisibility = true;
|
||||
|
||||
[Tooltip("Base visibility range (additional range beyond player vision)")]
|
||||
public float baseVisibilityRange = 10f;
|
||||
|
||||
[Tooltip("Visibility range multiplier per unit of height (default: 2x vision per 1m height)")]
|
||||
public float heightVisibilityMultiplier = 2.0f;
|
||||
|
||||
@@ -76,8 +82,17 @@ namespace Northbound
|
||||
// CRITICAL: Start hidden and stay hidden until fog system confirms visibility
|
||||
// Force initial hide - don't use SetVisible because _isVisible defaults to false
|
||||
// which would cause early return
|
||||
_isVisible = true; // Set to true first so SetVisible(false) actually runs
|
||||
SetVisible(false);
|
||||
// 단, alwaysVisible이면 항상 보임
|
||||
if (alwaysVisible)
|
||||
{
|
||||
_isVisible = false;
|
||||
SetVisible(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
_isVisible = true; // Set to true first so SetVisible(false) actually runs
|
||||
SetVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -165,21 +180,50 @@ namespace Northbound
|
||||
{
|
||||
if (NetworkManager.Singleton == null) return ulong.MaxValue;
|
||||
|
||||
var localPlayer = NetworkManager.Singleton.SpawnManager.GetLocalPlayerObject();
|
||||
if (localPlayer != null)
|
||||
// 방법 1: SpawnManager에서 찾기
|
||||
NetworkObject localPlayer = null;
|
||||
if (NetworkManager.Singleton.SpawnManager != null)
|
||||
{
|
||||
var playerController = localPlayer.GetComponent<NetworkPlayerController>();
|
||||
if (playerController != null)
|
||||
localPlayer = NetworkManager.Singleton.SpawnManager.GetLocalPlayerObject();
|
||||
}
|
||||
|
||||
// 방법 2: LocalClient에서 찾기
|
||||
if (localPlayer == null && NetworkManager.Singleton.LocalClient != null)
|
||||
{
|
||||
localPlayer = NetworkManager.Singleton.LocalClient.PlayerObject;
|
||||
}
|
||||
|
||||
// 방법 3: 직접 검색 (IsLocalPlayer인 플레이어 찾기)
|
||||
if (localPlayer == null)
|
||||
{
|
||||
var allPlayers = FindObjectsByType<NetworkPlayerController>(FindObjectsSortMode.None);
|
||||
foreach (var player in allPlayers)
|
||||
{
|
||||
return playerController.OwnerPlayerId;
|
||||
if (player.IsLocalPlayer)
|
||||
{
|
||||
localPlayer = player.GetComponent<NetworkObject>();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ulong.MaxValue;
|
||||
if (localPlayer == null) return ulong.MaxValue;
|
||||
|
||||
var playerController = localPlayer.GetComponent<NetworkPlayerController>();
|
||||
if (playerController == null) return ulong.MaxValue;
|
||||
|
||||
return playerController.OwnerPlayerId;
|
||||
}
|
||||
|
||||
private void UpdateVisibility()
|
||||
{
|
||||
// 항상 보이는 객체는 fog 체크 안함
|
||||
if (alwaysVisible)
|
||||
{
|
||||
SetVisible(true);
|
||||
return;
|
||||
}
|
||||
|
||||
var fogSystem = FogOfWarSystem.Instance;
|
||||
if (fogSystem == null)
|
||||
{
|
||||
@@ -268,11 +312,14 @@ namespace Northbound
|
||||
// Calculate extended visibility range based on height
|
||||
// Taller objects can be seen from farther away
|
||||
// Formula: Base range + (height - minHeight) * multiplier
|
||||
float extendedRange = (_objectHeight - minHeightForDistantVisibility) * heightVisibilityMultiplier;
|
||||
float extendedRange = 0f;
|
||||
if (_objectHeight >= minHeightForDistantVisibility)
|
||||
{
|
||||
extendedRange = (_objectHeight - minHeightForDistantVisibility) * heightVisibilityMultiplier;
|
||||
}
|
||||
|
||||
// Get player's vision range (assume average vision provider has ~15 unit range)
|
||||
float baseVisionRange = 15f; // You can make this configurable
|
||||
float totalRange = baseVisionRange + extendedRange;
|
||||
// Total range = player vision + base visibility + height bonus
|
||||
float totalRange = baseVisibilityRange + extendedRange;
|
||||
|
||||
return distanceToPlayer <= totalRange;
|
||||
}
|
||||
|
||||
@@ -3,8 +3,16 @@ using UnityEngine;
|
||||
|
||||
namespace Northbound
|
||||
{
|
||||
public class WorkerSpawner : NetworkBehaviour, IInteractable
|
||||
public class WorkerSpawner : NetworkBehaviour, IInteractable, IVisionProvider, ITeamMember
|
||||
{
|
||||
[Header("Vision Settings")]
|
||||
[Tooltip("워커 홀이 제공하는 시야 범위")]
|
||||
public float visionRange = 10f;
|
||||
|
||||
[Header("Team")]
|
||||
[Tooltip("건물의 팀")]
|
||||
public TeamType initialTeam = TeamType.Player;
|
||||
|
||||
[Header("Spawner Settings")]
|
||||
public GameObject workerPrefab;
|
||||
public Transform spawnPoint;
|
||||
@@ -34,11 +42,24 @@ namespace Northbound
|
||||
{
|
||||
base.OnNetworkSpawn();
|
||||
_workerCount.OnValueChanged += OnWorkerCountChanged;
|
||||
|
||||
if (IsServer)
|
||||
{
|
||||
// 시야 제공자로 등록
|
||||
FogOfWarSystem.Instance?.RegisterVisionProvider(this);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnNetworkDespawn()
|
||||
{
|
||||
_workerCount.OnValueChanged -= OnWorkerCountChanged;
|
||||
|
||||
if (IsServer)
|
||||
{
|
||||
// 시야 제공자 등록 해제
|
||||
FogOfWarSystem.Instance?.UnregisterVisionProvider(this);
|
||||
}
|
||||
|
||||
base.OnNetworkDespawn();
|
||||
}
|
||||
|
||||
@@ -240,9 +261,37 @@ namespace Northbound
|
||||
Vector3 spawnCenter = spawnPoint != null ? spawnPoint.position : transform.position;
|
||||
Gizmos.DrawWireSphere(spawnCenter, spawnRadius);
|
||||
|
||||
UnityEditor.Handles.Label(spawnCenter + Vector3.up * 2f,
|
||||
UnityEditor.Handles.Label(spawnCenter + Vector3.up * 2f,
|
||||
$"Worker Spawner\nWorkers: {_workerCount.Value}/{maxWorkers}");
|
||||
#endif
|
||||
}
|
||||
|
||||
#region IVisionProvider Implementation
|
||||
|
||||
public ulong GetOwnerId() => 0; // 워커 홀은 모든 플레이어에게 시야 제공
|
||||
|
||||
public float GetVisionRange() => visionRange;
|
||||
|
||||
Transform IVisionProvider.GetTransform() => transform;
|
||||
|
||||
public bool IsActive() => IsSpawned;
|
||||
|
||||
TeamType IVisionProvider.GetTeam() => initialTeam;
|
||||
|
||||
#endregion
|
||||
|
||||
#region ITeamMember Implementation
|
||||
|
||||
public TeamType GetTeam() => initialTeam;
|
||||
|
||||
public bool IsDead() => false; // 워커 홀은 파괴되지 않음
|
||||
|
||||
public void SetTeam(TeamType team)
|
||||
{
|
||||
// 워커 홀의 팀은 변경할 수 없음
|
||||
Debug.LogWarning("[WorkerSpawner] 워커 홀의 팀은 변경할 수 없습니다.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user