크립 캠프 내 모든 크립이 한번에 플레이어를 인식하도록 변경
This commit is contained in:
@@ -28,6 +28,11 @@ namespace Northbound
|
|||||||
private ResourcePickup _resourcePickup;
|
private ResourcePickup _resourcePickup;
|
||||||
private readonly Dictionary<EnemyUnit, System.Action<ulong>> _deathHandlers = new Dictionary<EnemyUnit, System.Action<ulong>>();
|
private readonly Dictionary<EnemyUnit, System.Action<ulong>> _deathHandlers = new Dictionary<EnemyUnit, System.Action<ulong>>();
|
||||||
|
|
||||||
|
// 중복 경고 방지용
|
||||||
|
private GameObject _lastAlertTarget;
|
||||||
|
private float _lastAlertTime;
|
||||||
|
private const float ALERT_COOLDOWN = 0.5f;
|
||||||
|
|
||||||
public override void OnNetworkSpawn()
|
public override void OnNetworkSpawn()
|
||||||
{
|
{
|
||||||
if (IsServer)
|
if (IsServer)
|
||||||
@@ -224,6 +229,39 @@ namespace Northbound
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 캠프 내 모든 크립에게 경고 전파
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target">감지된 타겟</param>
|
||||||
|
/// <param name="alertingCreep">경고를 보낸 크립 (자신에게는 다시 보내지 않음)</param>
|
||||||
|
public void AlertAllCreeps(GameObject target, EnemyAIController alertingCreep)
|
||||||
|
{
|
||||||
|
if (!IsServer) return;
|
||||||
|
if (target == null) return;
|
||||||
|
|
||||||
|
// 중복 경고 방지 (짧은 시간 내 같은 타겟에 대한 경고 무시)
|
||||||
|
if (_lastAlertTarget == target && Time.time - _lastAlertTime < ALERT_COOLDOWN)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_lastAlertTarget = target;
|
||||||
|
_lastAlertTime = Time.time;
|
||||||
|
|
||||||
|
// 캠프 내 모든 크립에게 경고 전파
|
||||||
|
foreach (var enemyUnit in _spawnedCreeps)
|
||||||
|
{
|
||||||
|
if (enemyUnit == null) continue;
|
||||||
|
|
||||||
|
EnemyAIController aiController = enemyUnit.GetComponent<EnemyAIController>();
|
||||||
|
if (aiController == null) continue;
|
||||||
|
|
||||||
|
// 경고를 보낸 크립은 제외 (이미 타겟을 설정했음)
|
||||||
|
if (aiController == alertingCreep) continue;
|
||||||
|
|
||||||
|
aiController.ReceiveAlert(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Rpc(SendTo.ClientsAndHost)]
|
[Rpc(SendTo.ClientsAndHost)]
|
||||||
private void EnableResourcePickupClientRpc()
|
private void EnableResourcePickupClientRpc()
|
||||||
{
|
{
|
||||||
@@ -286,6 +324,13 @@ namespace Northbound
|
|||||||
enemyUnit.OnDeath += handler;
|
enemyUnit.OnDeath += handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EnemyAIController에 캠프 참조 설정 (경고 전파 시스템용)
|
||||||
|
EnemyAIController aiController = creep.GetComponent<EnemyAIController>();
|
||||||
|
if (aiController != null)
|
||||||
|
{
|
||||||
|
aiController.creepCamp = this;
|
||||||
|
}
|
||||||
|
|
||||||
networkObj.SpawnWithOwnership(NetworkManager.Singleton.LocalClientId);
|
networkObj.SpawnWithOwnership(NetworkManager.Singleton.LocalClientId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,6 +61,10 @@ namespace Northbound
|
|||||||
[Header("Events")]
|
[Header("Events")]
|
||||||
public System.Action<GameObject> OnAttackPerformed;
|
public System.Action<GameObject> OnAttackPerformed;
|
||||||
|
|
||||||
|
[Header("Camp Alert System")]
|
||||||
|
[Tooltip("이 크립이 속한 캠프 (null이면 독립 크립)")]
|
||||||
|
public CreepCamp creepCamp;
|
||||||
|
|
||||||
private NavMeshAgent _agent;
|
private NavMeshAgent _agent;
|
||||||
private EnemyUnit _enemyUnit;
|
private EnemyUnit _enemyUnit;
|
||||||
private Core _core;
|
private Core _core;
|
||||||
@@ -164,6 +168,13 @@ namespace Northbound
|
|||||||
if (player != null)
|
if (player != null)
|
||||||
{
|
{
|
||||||
SetTargetPlayer(player);
|
SetTargetPlayer(player);
|
||||||
|
|
||||||
|
// 캠프 내 모든 크립에게 경고 전파
|
||||||
|
if (creepCamp != null)
|
||||||
|
{
|
||||||
|
creepCamp.AlertAllCreeps(player, this);
|
||||||
|
}
|
||||||
|
|
||||||
TransitionToState(EnemyAIState.ChasePlayer);
|
TransitionToState(EnemyAIState.ChasePlayer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -189,6 +200,13 @@ namespace Northbound
|
|||||||
if (detectedPlayer != null)
|
if (detectedPlayer != null)
|
||||||
{
|
{
|
||||||
SetTargetPlayer(detectedPlayer);
|
SetTargetPlayer(detectedPlayer);
|
||||||
|
|
||||||
|
// 캠프 내 모든 크립에게 경고 전파
|
||||||
|
if (creepCamp != null)
|
||||||
|
{
|
||||||
|
creepCamp.AlertAllCreeps(detectedPlayer, this);
|
||||||
|
}
|
||||||
|
|
||||||
TransitionToState(EnemyAIState.ChasePlayer);
|
TransitionToState(EnemyAIState.ChasePlayer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -723,6 +741,34 @@ namespace Northbound
|
|||||||
return _currentState.Value;
|
return _currentState.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 캠프 내 다른 크립으로부터 경고 전파 받음
|
||||||
|
/// </summary>
|
||||||
|
public void ReceiveAlert(GameObject target)
|
||||||
|
{
|
||||||
|
if (!IsServer) return;
|
||||||
|
if (target == null) return;
|
||||||
|
|
||||||
|
// 이미 해당 타겟을 추적 중이면 무시
|
||||||
|
if (_currentState.Value == EnemyAIState.ChasePlayer || _currentState.Value == EnemyAIState.Attack)
|
||||||
|
{
|
||||||
|
GameObject currentTarget = GetTargetPlayer();
|
||||||
|
if (currentTarget == target) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 이미 사망한 타겟은 무시
|
||||||
|
IDamageable damageable = target.GetComponentInParent<IDamageable>();
|
||||||
|
if (damageable != null && damageable.IsDead()) return;
|
||||||
|
|
||||||
|
// 타겟 설정 및 추적 시작
|
||||||
|
SetTargetPlayer(target);
|
||||||
|
|
||||||
|
if (_currentState.Value == EnemyAIState.Idle || _currentState.Value == EnemyAIState.MoveToCore)
|
||||||
|
{
|
||||||
|
TransitionToState(EnemyAIState.ChasePlayer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Gizmos (기존 코드 유지)
|
#region Gizmos (기존 코드 유지)
|
||||||
|
|||||||
Reference in New Issue
Block a user