파괴 가능 오브젝트에 대해서 피격 시 로그를 남기도록 함

This commit is contained in:
2026-02-16 09:52:14 +09:00
parent 047c115f95
commit 5bb8cd533e
3 changed files with 149 additions and 1 deletions

View File

@@ -93,6 +93,8 @@ namespace Northbound
int actualDamage = Mathf.Min(damage, _currentHealth.Value); int actualDamage = Mathf.Min(damage, _currentHealth.Value);
_currentHealth.Value -= actualDamage; _currentHealth.Value -= actualDamage;
Debug.Log($"<color=red>[Core] 코어가 {actualDamage} 데미지를 받았습니다. 남은 체력: {_currentHealth.Value}/{maxHealth}</color>");
// 데미지 이펙트 // 데미지 이펙트
ShowDamageEffectClientRpc(); ShowDamageEffectClientRpc();

View File

@@ -4,8 +4,32 @@ using System.Collections.Generic;
using Unity.Netcode; using Unity.Netcode;
using UnityEngine; using UnityEngine;
public class EnemyPortal : NetworkBehaviour public class EnemyPortal : NetworkBehaviour, IDamageable, ITeamMember
{ {
[Header("Team Settings")]
[Tooltip("포털의 팀 (Hostile 또는 Monster)")]
[SerializeField] private TeamType portalTeam = TeamType.Hostile;
[Header("Health Settings")]
[Tooltip("최대 체력")]
[SerializeField] private int maxHealth = 500;
[Header("Visual Effects")]
[SerializeField] private GameObject damageEffectPrefab;
[SerializeField] private GameObject destroyEffectPrefab;
[SerializeField] private Transform effectSpawnPoint;
private NetworkVariable<int> _currentHealth = new NetworkVariable<int>(
0,
NetworkVariableReadPermission.Everyone,
NetworkVariableWritePermission.Server
);
private NetworkVariable<TeamType> _team = new NetworkVariable<TeamType>(
TeamType.Neutral,
NetworkVariableReadPermission.Everyone,
NetworkVariableWritePermission.Server
);
[System.Serializable] [System.Serializable]
public class MonsterEntry public class MonsterEntry
{ {
@@ -27,12 +51,33 @@ using UnityEngine;
public override void OnNetworkSpawn() public override void OnNetworkSpawn()
{ {
base.OnNetworkSpawn(); base.OnNetworkSpawn();
if (IsServer)
{
// 체력 초기화
if (_currentHealth.Value == 0)
{
_currentHealth.Value = maxHealth;
}
// 팀 초기화
if (_team.Value == TeamType.Neutral)
{
_team.Value = portalTeam;
}
Debug.Log($"<color=cyan>[EnemyPortal] 포털 스폰됨 (팀: {TeamManager.GetTeamName(_team.Value)}, 체력: {_currentHealth.Value}/{maxHealth})</color>");
}
GlobalTimer.Instance.OnCycleStart += OnCycleStart; GlobalTimer.Instance.OnCycleStart += OnCycleStart;
} }
public override void OnNetworkDespawn() public override void OnNetworkDespawn()
{ {
GlobalTimer.Instance.OnCycleStart -= OnCycleStart; GlobalTimer.Instance.OnCycleStart -= OnCycleStart;
// 체력 변경 이벤트 정리 (나중에 추가할 경우 대비)
base.OnNetworkDespawn(); base.OnNetworkDespawn();
} }
@@ -163,4 +208,103 @@ using UnityEngine;
{ {
currentCost *= (1f + costIncreaseRate / 100f); currentCost *= (1f + costIncreaseRate / 100f);
} }
#region ITeamMember Implementation
public TeamType GetTeam() => _team.Value;
public void SetTeam(TeamType team)
{
if (!IsServer) return;
_team.Value = team;
}
#endregion
#region IDamageable Implementation
public void TakeDamage(int damage, ulong attackerId)
{
if (!IsServer) return;
// 이미 파괴됨
if (_currentHealth.Value <= 0) return;
// 공격자의 팀 확인
if (NetworkManager.Singleton.SpawnManager.SpawnedObjects.TryGetValue(attackerId, out NetworkObject attackerObj))
{
var attackerTeamMember = attackerObj.GetComponent<ITeamMember>();
if (attackerTeamMember != null)
{
if (!TeamManager.CanAttack(attackerTeamMember, this))
{
Debug.Log($"<color=yellow>[EnemyPortal] {TeamManager.GetTeamName(attackerTeamMember.GetTeam())} 팀은 {TeamManager.GetTeamName(_team.Value)} 팀 포털을 공격할 수 없습니다.</color>");
return;
}
}
}
// 데미지 적용
int actualDamage = Mathf.Min(damage, _currentHealth.Value);
_currentHealth.Value -= actualDamage;
Debug.Log($"<color=red>[EnemyPortal] 포털이 {actualDamage} 데미지를 받았습니다. 남은 체력: {_currentHealth.Value}/{maxHealth}</color>");
// 데미지 이펙트
ShowDamageEffectClientRpc();
// 체력이 0이 되면 파괴
if (_currentHealth.Value <= 0)
{
DestroyPortal(attackerId);
}
}
private void DestroyPortal(ulong attackerId)
{
if (!IsServer) return;
Debug.Log($"<color=red>[EnemyPortal] 포털이 파괴되었습니다! (공격자: {attackerId})</color>");
// 파괴 이펙트
ShowDestroyEffectClientRpc();
// 몬스터 스폰 중지 (이벤트 구독 해제)
GlobalTimer.Instance.OnCycleStart -= OnCycleStart;
// 네트워크 오브젝트 파괴 (약간의 딜레이)
Invoke(nameof(DespawnPortal), 1.0f);
}
private void DespawnPortal()
{
if (IsServer && NetworkObject != null)
{
NetworkObject.Despawn(true);
}
}
[ClientRpc]
private void ShowDamageEffectClientRpc()
{
if (damageEffectPrefab != null)
{
Transform spawnPoint = effectSpawnPoint != null ? effectSpawnPoint : transform;
GameObject effect = Instantiate(damageEffectPrefab, spawnPoint.position, spawnPoint.rotation);
Destroy(effect, 2f);
}
}
[ClientRpc]
private void ShowDestroyEffectClientRpc()
{
if (destroyEffectPrefab != null)
{
Transform spawnPoint = effectSpawnPoint != null ? effectSpawnPoint : transform;
GameObject effect = Instantiate(destroyEffectPrefab, spawnPoint.position, spawnPoint.rotation);
Destroy(effect, 3f);
}
}
#endregion
} }

View File

@@ -76,6 +76,8 @@ namespace Northbound
int actualDamage = Mathf.Min(damage, _currentHealth.Value); int actualDamage = Mathf.Min(damage, _currentHealth.Value);
_currentHealth.Value -= actualDamage; _currentHealth.Value -= actualDamage;
Debug.Log($"<color=red>[EnemyUnit] 적 유닛이 {actualDamage} 데미지를 받았습니다. 남은 체력: {_currentHealth.Value}/{maxHealth}</color>");
// 데미지 이펙트 // 데미지 이펙트
ShowDamageEffectClientRpc(); ShowDamageEffectClientRpc();