기본 배치 건물이 시야를 제공하도록 변경
This commit is contained in:
@@ -38,7 +38,7 @@ namespace Northbound.Data
|
|||||||
public int length => sizeZ; // Z축 (깊이)
|
public int length => sizeZ; // Z축 (깊이)
|
||||||
public float height => sizeY; // Y축 (높이)
|
public float height => sizeY; // Y축 (높이)
|
||||||
public int maxHealth => maxHp;
|
public int maxHealth => maxHp;
|
||||||
public float visionRange => atkRange;
|
public float visionRange => sight;
|
||||||
public float requiredWorkAmount => manpower;
|
public float requiredWorkAmount => manpower;
|
||||||
|
|
||||||
public Vector3 GetSize(int rotation)
|
public Vector3 GetSize(int rotation)
|
||||||
|
|||||||
47
Assets/Prefabs/Core.asset
Normal file
47
Assets/Prefabs/Core.asset
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!114 &11400000
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 8c40fef5ebc37b743a3f225c1ca57c32, type: 3}
|
||||||
|
m_Name: Core
|
||||||
|
m_EditorClassIdentifier: Assembly-CSharp::Northbound.Data.TowerData
|
||||||
|
id: 0
|
||||||
|
memo:
|
||||||
|
buildingName:
|
||||||
|
level: 0
|
||||||
|
upgradeTo: 0
|
||||||
|
towerType:
|
||||||
|
mana: 0
|
||||||
|
manpower: 0
|
||||||
|
sizeX: 0
|
||||||
|
sizeY: 0
|
||||||
|
sizeZ: 0
|
||||||
|
maxHp: 0
|
||||||
|
sight: 100
|
||||||
|
atkRange: 0
|
||||||
|
atkDamage: 0
|
||||||
|
atkIntervalSec: 0
|
||||||
|
modelPath:
|
||||||
|
prefab: {fileID: 0}
|
||||||
|
icon: {fileID: 0}
|
||||||
|
placementOffset: {x: 0, y: 0, z: 0}
|
||||||
|
allowRotation: 1
|
||||||
|
isIndestructible: 0
|
||||||
|
autoRegenerate: 0
|
||||||
|
regenPerSecond: 1
|
||||||
|
providesVision: 1
|
||||||
|
constructionEquipment:
|
||||||
|
socketName: RightHand
|
||||||
|
equipmentPrefab: {fileID: 0}
|
||||||
|
attachOnStart: 1
|
||||||
|
detachOnEnd: 1
|
||||||
|
keepEquipped: 0
|
||||||
|
attachDelay: 0
|
||||||
|
detachDelay: 0
|
||||||
8
Assets/Prefabs/Core.asset.meta
Normal file
8
Assets/Prefabs/Core.asset.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8e9cb7f0c2209b543b171709534789aa
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 11400000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -49,7 +49,7 @@ MonoBehaviour:
|
|||||||
m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3}
|
m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier: Unity.Netcode.Runtime::Unity.Netcode.NetworkObject
|
m_EditorClassIdentifier: Unity.Netcode.Runtime::Unity.Netcode.NetworkObject
|
||||||
GlobalObjectIdHash: 3998537868
|
GlobalObjectIdHash: 615747208
|
||||||
InScenePlacedSourceGlobalObjectIdHash: 615747208
|
InScenePlacedSourceGlobalObjectIdHash: 615747208
|
||||||
DeferredDespawnTick: 0
|
DeferredDespawnTick: 0
|
||||||
Ownership: 0
|
Ownership: 0
|
||||||
@@ -106,7 +106,7 @@ MonoBehaviour:
|
|||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier: Assembly-CSharp::Northbound.Building
|
m_EditorClassIdentifier: Assembly-CSharp::Northbound.Building
|
||||||
ShowTopMostFoldoutHeaderGroup: 1
|
ShowTopMostFoldoutHeaderGroup: 1
|
||||||
buildingData: {fileID: 0}
|
buildingData: {fileID: 11400000, guid: 8e9cb7f0c2209b543b171709534789aa, type: 2}
|
||||||
gridPosition: {x: 0, y: 0, z: 0}
|
gridPosition: {x: 0, y: 0, z: 0}
|
||||||
rotation: 0
|
rotation: 0
|
||||||
initialTeam: 1
|
initialTeam: 1
|
||||||
@@ -152,10 +152,12 @@ MonoBehaviour:
|
|||||||
m_Script: {fileID: 11500000, guid: 760137a2fd0da7f458ac4b0ee7f485d6, type: 3}
|
m_Script: {fileID: 11500000, guid: 760137a2fd0da7f458ac4b0ee7f485d6, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier: Assembly-CSharp::Northbound.FogOfWarVisibility
|
m_EditorClassIdentifier: Assembly-CSharp::Northbound.FogOfWarVisibility
|
||||||
|
alwaysVisible: 1
|
||||||
showInExploredAreas: 1
|
showInExploredAreas: 1
|
||||||
updateInterval: 0.2
|
updateInterval: 0.2
|
||||||
renderers: []
|
renderers: []
|
||||||
enableDistantVisibility: 1
|
enableDistantVisibility: 1
|
||||||
|
baseVisibilityRange: 50
|
||||||
heightVisibilityMultiplier: 2
|
heightVisibilityMultiplier: 2
|
||||||
minHeightForDistantVisibility: 3
|
minHeightForDistantVisibility: 3
|
||||||
useExploredMaterial: 0
|
useExploredMaterial: 0
|
||||||
|
|||||||
@@ -6,8 +6,16 @@ namespace Northbound
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 블랙스미스 건물 - 업그레이드 구매 가능
|
/// 블랙스미스 건물 - 업그레이드 구매 가능
|
||||||
/// </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")]
|
[Header("UI Reference")]
|
||||||
[SerializeField] private GameObject _upgradePopupPrefab;
|
[SerializeField] private GameObject _upgradePopupPrefab;
|
||||||
|
|
||||||
@@ -55,9 +63,6 @@ namespace Northbound
|
|||||||
return transform;
|
return transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private void OpenUpgradePopup(ulong playerId)
|
private void OpenUpgradePopup(ulong playerId)
|
||||||
@@ -115,12 +120,63 @@ namespace Northbound
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDestroy()
|
public override void OnDestroy()
|
||||||
{
|
{
|
||||||
if (_popupInstance != null)
|
if (_popupInstance != null)
|
||||||
{
|
{
|
||||||
Destroy(_popupInstance);
|
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>
|
||||||
/// 플레이어가 자원을 건내받아 게임의 전역 자원으로 관리하는 중앙 허브
|
/// 플레이어가 자원을 건내받아 게임의 전역 자원으로 관리하는 중앙 허브
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Core : NetworkBehaviour, IInteractable, IDamageable, ITeamMember
|
public class Core : NetworkBehaviour, IInteractable, IDamageable, ITeamMember, IVisionProvider
|
||||||
{
|
{
|
||||||
[Header("Core Settings")]
|
[Header("Core Settings")]
|
||||||
public int maxStorageCapacity = 1000; // 코어의 최대 저장 용량
|
public int maxStorageCapacity = 1000; // 코어의 최대 저장 용량
|
||||||
public bool unlimitedStorage = false; // 무제한 저장소
|
public bool unlimitedStorage = false; // 무제한 저장소
|
||||||
|
|
||||||
|
[Header("Vision")]
|
||||||
|
public float visionRange = 15f; // 코어가 제공하는 시야 범위
|
||||||
|
|
||||||
[Header("Health")]
|
[Header("Health")]
|
||||||
public int maxHealth = 1000;
|
public int maxHealth = 1000;
|
||||||
public GameObject damageEffectPrefab;
|
public GameObject damageEffectPrefab;
|
||||||
@@ -55,6 +58,9 @@ namespace Northbound
|
|||||||
{
|
{
|
||||||
_totalResources.Value = 0;
|
_totalResources.Value = 0;
|
||||||
_currentHealth.Value = maxHealth;
|
_currentHealth.Value = maxHealth;
|
||||||
|
|
||||||
|
// 시야 제공자로 등록
|
||||||
|
FogOfWarSystem.Instance?.RegisterVisionProvider(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
_currentHealth.OnValueChanged += OnHealthChanged;
|
_currentHealth.OnValueChanged += OnHealthChanged;
|
||||||
@@ -62,6 +68,12 @@ namespace Northbound
|
|||||||
|
|
||||||
public override void OnNetworkDespawn()
|
public override void OnNetworkDespawn()
|
||||||
{
|
{
|
||||||
|
if (IsServer)
|
||||||
|
{
|
||||||
|
// 시야 제공자 등록 해제
|
||||||
|
FogOfWarSystem.Instance?.UnregisterVisionProvider(this);
|
||||||
|
}
|
||||||
|
|
||||||
_currentHealth.OnValueChanged -= OnHealthChanged;
|
_currentHealth.OnValueChanged -= OnHealthChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,5 +384,19 @@ namespace Northbound
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#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;
|
if (NetworkManager.Singleton == null) return ulong.MaxValue;
|
||||||
|
|
||||||
var localPlayer = NetworkManager.Singleton.SpawnManager.GetLocalPlayerObject();
|
// 방법 1: SpawnManager에서 찾기
|
||||||
if (localPlayer != null)
|
NetworkObject localPlayer = null;
|
||||||
|
if (NetworkManager.Singleton.SpawnManager != null)
|
||||||
{
|
{
|
||||||
var playerController = localPlayer.GetComponent<NetworkPlayerController>();
|
localPlayer = NetworkManager.Singleton.SpawnManager.GetLocalPlayerObject();
|
||||||
if (playerController != null)
|
}
|
||||||
|
|
||||||
|
// 방법 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>
|
/// <summary>
|
||||||
|
|||||||
@@ -307,7 +307,8 @@ namespace Northbound
|
|||||||
if (!_visionProviders.Contains(provider))
|
if (!_visionProviders.Contains(provider))
|
||||||
{
|
{
|
||||||
_visionProviders.Add(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
|
public class FogOfWarVisibility : MonoBehaviour
|
||||||
{
|
{
|
||||||
[Header("Visibility Settings")]
|
[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")]
|
[Tooltip("Show this object in explored areas (greyed out) or only when visible")]
|
||||||
public bool showInExploredAreas = false;
|
public bool showInExploredAreas = false;
|
||||||
|
|
||||||
@@ -19,10 +22,13 @@ namespace Northbound
|
|||||||
[Tooltip("Renderers to show/hide (auto-detected if empty)")]
|
[Tooltip("Renderers to show/hide (auto-detected if empty)")]
|
||||||
public Renderer[] renderers;
|
public Renderer[] renderers;
|
||||||
|
|
||||||
[Header("Height-Based Distant Visibility")]
|
[Header("Extended Visibility")]
|
||||||
[Tooltip("Enable visibility from farther away based on object height")]
|
[Tooltip("Enable visibility from farther away based on object height")]
|
||||||
public bool enableDistantVisibility = true;
|
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)")]
|
[Tooltip("Visibility range multiplier per unit of height (default: 2x vision per 1m height)")]
|
||||||
public float heightVisibilityMultiplier = 2.0f;
|
public float heightVisibilityMultiplier = 2.0f;
|
||||||
|
|
||||||
@@ -76,8 +82,17 @@ namespace Northbound
|
|||||||
// CRITICAL: Start hidden and stay hidden until fog system confirms visibility
|
// CRITICAL: Start hidden and stay hidden until fog system confirms visibility
|
||||||
// Force initial hide - don't use SetVisible because _isVisible defaults to false
|
// Force initial hide - don't use SetVisible because _isVisible defaults to false
|
||||||
// which would cause early return
|
// which would cause early return
|
||||||
_isVisible = true; // Set to true first so SetVisible(false) actually runs
|
// 단, alwaysVisible이면 항상 보임
|
||||||
SetVisible(false);
|
if (alwaysVisible)
|
||||||
|
{
|
||||||
|
_isVisible = false;
|
||||||
|
SetVisible(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_isVisible = true; // Set to true first so SetVisible(false) actually runs
|
||||||
|
SetVisible(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -165,21 +180,50 @@ namespace Northbound
|
|||||||
{
|
{
|
||||||
if (NetworkManager.Singleton == null) return ulong.MaxValue;
|
if (NetworkManager.Singleton == null) return ulong.MaxValue;
|
||||||
|
|
||||||
var localPlayer = NetworkManager.Singleton.SpawnManager.GetLocalPlayerObject();
|
// 방법 1: SpawnManager에서 찾기
|
||||||
if (localPlayer != null)
|
NetworkObject localPlayer = null;
|
||||||
|
if (NetworkManager.Singleton.SpawnManager != null)
|
||||||
{
|
{
|
||||||
var playerController = localPlayer.GetComponent<NetworkPlayerController>();
|
localPlayer = NetworkManager.Singleton.SpawnManager.GetLocalPlayerObject();
|
||||||
if (playerController != null)
|
}
|
||||||
|
|
||||||
|
// 방법 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()
|
private void UpdateVisibility()
|
||||||
{
|
{
|
||||||
|
// 항상 보이는 객체는 fog 체크 안함
|
||||||
|
if (alwaysVisible)
|
||||||
|
{
|
||||||
|
SetVisible(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var fogSystem = FogOfWarSystem.Instance;
|
var fogSystem = FogOfWarSystem.Instance;
|
||||||
if (fogSystem == null)
|
if (fogSystem == null)
|
||||||
{
|
{
|
||||||
@@ -268,11 +312,14 @@ namespace Northbound
|
|||||||
// Calculate extended visibility range based on height
|
// Calculate extended visibility range based on height
|
||||||
// Taller objects can be seen from farther away
|
// Taller objects can be seen from farther away
|
||||||
// Formula: Base range + (height - minHeight) * multiplier
|
// 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)
|
// Total range = player vision + base visibility + height bonus
|
||||||
float baseVisionRange = 15f; // You can make this configurable
|
float totalRange = baseVisibilityRange + extendedRange;
|
||||||
float totalRange = baseVisionRange + extendedRange;
|
|
||||||
|
|
||||||
return distanceToPlayer <= totalRange;
|
return distanceToPlayer <= totalRange;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,16 @@ using UnityEngine;
|
|||||||
|
|
||||||
namespace Northbound
|
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")]
|
[Header("Spawner Settings")]
|
||||||
public GameObject workerPrefab;
|
public GameObject workerPrefab;
|
||||||
public Transform spawnPoint;
|
public Transform spawnPoint;
|
||||||
@@ -34,11 +42,24 @@ namespace Northbound
|
|||||||
{
|
{
|
||||||
base.OnNetworkSpawn();
|
base.OnNetworkSpawn();
|
||||||
_workerCount.OnValueChanged += OnWorkerCountChanged;
|
_workerCount.OnValueChanged += OnWorkerCountChanged;
|
||||||
|
|
||||||
|
if (IsServer)
|
||||||
|
{
|
||||||
|
// 시야 제공자로 등록
|
||||||
|
FogOfWarSystem.Instance?.RegisterVisionProvider(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnNetworkDespawn()
|
public override void OnNetworkDespawn()
|
||||||
{
|
{
|
||||||
_workerCount.OnValueChanged -= OnWorkerCountChanged;
|
_workerCount.OnValueChanged -= OnWorkerCountChanged;
|
||||||
|
|
||||||
|
if (IsServer)
|
||||||
|
{
|
||||||
|
// 시야 제공자 등록 해제
|
||||||
|
FogOfWarSystem.Instance?.UnregisterVisionProvider(this);
|
||||||
|
}
|
||||||
|
|
||||||
base.OnNetworkDespawn();
|
base.OnNetworkDespawn();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,9 +261,37 @@ namespace Northbound
|
|||||||
Vector3 spawnCenter = spawnPoint != null ? spawnPoint.position : transform.position;
|
Vector3 spawnCenter = spawnPoint != null ? spawnPoint.position : transform.position;
|
||||||
Gizmos.DrawWireSphere(spawnCenter, spawnRadius);
|
Gizmos.DrawWireSphere(spawnCenter, spawnRadius);
|
||||||
|
|
||||||
UnityEditor.Handles.Label(spawnCenter + Vector3.up * 2f,
|
UnityEditor.Handles.Label(spawnCenter + Vector3.up * 2f,
|
||||||
$"Worker Spawner\nWorkers: {_workerCount.Value}/{maxWorkers}");
|
$"Worker Spawner\nWorkers: {_workerCount.Value}/{maxWorkers}");
|
||||||
#endif
|
#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