플레이어/적/몬스터 팀 시스템 생성
몬스터 및 적 AI 구현
This commit is contained in:
@@ -4,7 +4,7 @@ using UnityEngine;
|
||||
|
||||
namespace Northbound
|
||||
{
|
||||
public class Building : NetworkBehaviour, IDamageable, IVisionProvider
|
||||
public class Building : NetworkBehaviour, IDamageable, IVisionProvider, ITeamMember
|
||||
{
|
||||
[Header("References")]
|
||||
public BuildingData buildingData;
|
||||
@@ -13,6 +13,10 @@ namespace Northbound
|
||||
public Vector3Int gridPosition;
|
||||
public int rotation; // 0-3 (0=0°, 1=90°, 2=180°, 3=270°)
|
||||
|
||||
[Header("Team")]
|
||||
[Tooltip("건물의 팀 (플레이어/적대세력/몬스터/중립)")]
|
||||
public TeamType initialTeam = TeamType.Player;
|
||||
|
||||
[Header("Ownership (for pre-placed buildings)")]
|
||||
[Tooltip("씬에 미리 배치된 건물의 경우 여기서 소유자 설정 (0 = 중립, 1+ = 플레이어 ID)")]
|
||||
public ulong initialOwnerId = 0;
|
||||
@@ -46,9 +50,17 @@ namespace Northbound
|
||||
NetworkVariableWritePermission.Server
|
||||
);
|
||||
|
||||
// 건물 팀
|
||||
private NetworkVariable<TeamType> _team = new NetworkVariable<TeamType>(
|
||||
TeamType.Neutral,
|
||||
NetworkVariableReadPermission.Everyone,
|
||||
NetworkVariableWritePermission.Server
|
||||
);
|
||||
|
||||
// 이벤트
|
||||
public event Action<int, int> OnHealthChanged; // (current, max)
|
||||
public event Action OnDestroyed;
|
||||
public event Action<TeamType> OnTeamChanged;
|
||||
|
||||
private BuildingHealthBar _healthBar;
|
||||
private float _lastRegenTime;
|
||||
@@ -66,11 +78,17 @@ namespace Northbound
|
||||
_currentHealth.Value = buildingData != null ? buildingData.maxHealth : 100;
|
||||
}
|
||||
|
||||
// 팀 초기화
|
||||
if (_team.Value == TeamType.Neutral)
|
||||
{
|
||||
_team.Value = initialTeam;
|
||||
}
|
||||
|
||||
// 소유자 초기화 (사전 배치 건물 체크)
|
||||
if (useInitialOwner && _ownerId.Value == 0)
|
||||
{
|
||||
_ownerId.Value = initialOwnerId;
|
||||
Debug.Log($"<color=cyan>[Building] 사전 배치 건물 '{buildingData?.buildingName ?? gameObject.name}' 소유자: {initialOwnerId}</color>");
|
||||
Debug.Log($"<color=cyan>[Building] 사전 배치 건물 '{buildingData?.buildingName ?? gameObject.name}' 소유자: {initialOwnerId}, 팀: {_team.Value}</color>");
|
||||
}
|
||||
else if (!useInitialOwner && _ownerId.Value == 0)
|
||||
{
|
||||
@@ -87,8 +105,9 @@ namespace Northbound
|
||||
}
|
||||
}
|
||||
|
||||
// 체력 변경 이벤트 구독
|
||||
// 이벤트 구독
|
||||
_currentHealth.OnValueChanged += OnHealthValueChanged;
|
||||
_team.OnValueChanged += OnTeamValueChanged;
|
||||
|
||||
// 체력바 생성
|
||||
if (showHealthBar && healthBarPrefab != null)
|
||||
@@ -98,11 +117,13 @@ namespace Northbound
|
||||
|
||||
// 초기 체력 UI 업데이트
|
||||
UpdateHealthUI();
|
||||
UpdateTeamVisuals();
|
||||
}
|
||||
|
||||
public override void OnNetworkDespawn()
|
||||
{
|
||||
_currentHealth.OnValueChanged -= OnHealthValueChanged;
|
||||
_team.OnValueChanged -= OnTeamValueChanged;
|
||||
|
||||
// FogOfWar 시스템에서 제거
|
||||
if (IsServer && buildingData != null && buildingData.providesVision)
|
||||
@@ -131,7 +152,7 @@ namespace Northbound
|
||||
/// <summary>
|
||||
/// 건물 초기화 (BuildingManager가 동적 생성 시 호출)
|
||||
/// </summary>
|
||||
public void Initialize(BuildingData data, Vector3Int gridPos, int rot, ulong ownerId)
|
||||
public void Initialize(BuildingData data, Vector3Int gridPos, int rot, ulong ownerId, TeamType team = TeamType.Player)
|
||||
{
|
||||
buildingData = data;
|
||||
gridPosition = gridPos;
|
||||
@@ -142,6 +163,7 @@ namespace Northbound
|
||||
{
|
||||
_currentHealth.Value = data.maxHealth;
|
||||
_ownerId.Value = ownerId;
|
||||
_team.Value = team;
|
||||
|
||||
// 시야 제공자 등록
|
||||
if (data.providesVision)
|
||||
@@ -156,14 +178,17 @@ namespace Northbound
|
||||
/// <summary>
|
||||
/// 건물 소유권 변경 (점령 등)
|
||||
/// </summary>
|
||||
public void SetOwner(ulong newOwnerId)
|
||||
public void SetOwner(ulong newOwnerId, TeamType newTeam)
|
||||
{
|
||||
if (!IsServer) return;
|
||||
|
||||
ulong previousOwner = _ownerId.Value;
|
||||
TeamType previousTeam = _team.Value;
|
||||
|
||||
_ownerId.Value = newOwnerId;
|
||||
_team.Value = newTeam;
|
||||
|
||||
Debug.Log($"<color=yellow>[Building] {buildingData?.buildingName ?? "건물"} 소유권 변경: {previousOwner} → {newOwnerId}</color>");
|
||||
Debug.Log($"<color=yellow>[Building] {buildingData?.buildingName ?? "건물"} 소유권 변경: {previousOwner} → {newOwnerId}, 팀: {TeamManager.GetTeamName(previousTeam)} → {TeamManager.GetTeamName(newTeam)}</color>");
|
||||
|
||||
// 시야 제공자 재등록 (소유자가 바뀌었으므로)
|
||||
if (buildingData != null && buildingData.providesVision)
|
||||
@@ -173,6 +198,35 @@ namespace Northbound
|
||||
}
|
||||
}
|
||||
|
||||
#region ITeamMember Implementation
|
||||
|
||||
public TeamType GetTeam() => _team.Value;
|
||||
|
||||
public void SetTeam(TeamType team)
|
||||
{
|
||||
if (!IsServer) return;
|
||||
_team.Value = team;
|
||||
}
|
||||
|
||||
private void OnTeamValueChanged(TeamType previousValue, TeamType newValue)
|
||||
{
|
||||
OnTeamChanged?.Invoke(newValue);
|
||||
UpdateTeamVisuals();
|
||||
Debug.Log($"<color=cyan>[Building] {buildingData?.buildingName ?? "건물"} 팀 변경: {TeamManager.GetTeamName(previousValue)} → {TeamManager.GetTeamName(newValue)}</color>");
|
||||
}
|
||||
|
||||
private void UpdateTeamVisuals()
|
||||
{
|
||||
// 팀 색상으로 건물 외곽선이나 이펙트 변경 가능
|
||||
// 예: Renderer의 emission 색상 변경
|
||||
Color teamColor = TeamManager.GetTeamColor(_team.Value);
|
||||
|
||||
// 여기에 실제 비주얼 업데이트 로직 추가
|
||||
// 예: outline shader, emission, particle system 색상 등
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IVisionProvider Implementation
|
||||
|
||||
public ulong GetOwnerId() => _ownerId.Value;
|
||||
@@ -214,11 +268,24 @@ namespace Northbound
|
||||
if (_currentHealth.Value <= 0)
|
||||
return;
|
||||
|
||||
// 공격자의 팀 확인 (팀 공격 방지)
|
||||
var attackerObj = NetworkManager.Singleton.SpawnManager.SpawnedObjects[attackerId];
|
||||
var attackerTeamMember = attackerObj?.GetComponent<ITeamMember>();
|
||||
|
||||
if (attackerTeamMember != null)
|
||||
{
|
||||
if (!TeamManager.CanAttack(attackerTeamMember, this))
|
||||
{
|
||||
Debug.Log($"<color=yellow>[Building] {TeamManager.GetTeamName(attackerTeamMember.GetTeam())} 팀은 {TeamManager.GetTeamName(_team.Value)} 팀을 공격할 수 없습니다.</color>");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 데미지 적용
|
||||
int actualDamage = Mathf.Min(damage, _currentHealth.Value);
|
||||
_currentHealth.Value -= actualDamage;
|
||||
|
||||
Debug.Log($"<color=red>[Building] {buildingData?.buildingName ?? "건물"}이(가) {actualDamage} 데미지를 받았습니다. 남은 체력: {_currentHealth.Value}/{buildingData?.maxHealth ?? 100}</color>");
|
||||
Debug.Log($"<color=red>[Building] {buildingData?.buildingName ?? "건물"} ({TeamManager.GetTeamName(_team.Value)})이(가) {actualDamage} 데미지를 받았습니다. 남은 체력: {_currentHealth.Value}/{buildingData?.maxHealth ?? 100}</color>");
|
||||
|
||||
// 데미지 이펙트
|
||||
ShowDamageEffectClientRpc();
|
||||
@@ -248,7 +315,7 @@ namespace Northbound
|
||||
if (!IsServer)
|
||||
return;
|
||||
|
||||
Debug.Log($"<color=red>[Building] {buildingData?.buildingName ?? "건물"}이(가) 파괴되었습니다! (공격자: {attackerId})</color>");
|
||||
Debug.Log($"<color=red>[Building] {buildingData?.buildingName ?? "건물"} ({TeamManager.GetTeamName(_team.Value)})이(가) 파괴되었습니다! (공격자: {attackerId})</color>");
|
||||
|
||||
// 파괴 이벤트 발생
|
||||
OnDestroyed?.Invoke();
|
||||
@@ -427,7 +494,10 @@ namespace Northbound
|
||||
if (!showGridBounds || buildingData == null) return;
|
||||
|
||||
Bounds bounds = GetGridBounds();
|
||||
Gizmos.color = gridBoundsColor;
|
||||
|
||||
// 팀 색상으로 표시
|
||||
Color teamColor = Application.isPlaying ? TeamManager.GetTeamColor(_team.Value) : TeamManager.GetTeamColor(initialTeam);
|
||||
Gizmos.color = new Color(teamColor.r, teamColor.g, teamColor.b, 0.3f);
|
||||
Gizmos.DrawWireCube(bounds.center, bounds.size);
|
||||
}
|
||||
|
||||
@@ -454,17 +524,19 @@ namespace Northbound
|
||||
Gizmos.DrawWireSphere(transform.position, buildingData.visionRange);
|
||||
}
|
||||
|
||||
// Draw owner ID label
|
||||
// Draw team info label
|
||||
#if UNITY_EDITOR
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
string teamName = TeamManager.GetTeamName(_team.Value);
|
||||
UnityEditor.Handles.Label(transform.position + Vector3.up * 3f,
|
||||
$"Owner: {_ownerId.Value}");
|
||||
$"Owner: {_ownerId.Value}\nTeam: {teamName}");
|
||||
}
|
||||
else if (useInitialOwner)
|
||||
{
|
||||
string teamName = TeamManager.GetTeamName(initialTeam);
|
||||
UnityEditor.Handles.Label(transform.position + Vector3.up * 3f,
|
||||
$"Initial Owner: {initialOwnerId}");
|
||||
$"Initial Owner: {initialOwnerId}\nTeam: {teamName}");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user