네트워크 멀티플레이 대응

This commit is contained in:
2026-01-31 20:49:23 +09:00
parent 1152093521
commit c5bcf265d0
69 changed files with 2766 additions and 1392 deletions

View File

@@ -31,8 +31,14 @@ namespace Northbound
private Animator _animator;
private ITeamMember _teamMember;
private EquipmentSocket _equipmentSocket;
private bool _isAttacking = false;
private NetworkVariable<bool> _isAttacking = new NetworkVariable<bool>(
false,
NetworkVariableReadPermission.Everyone,
NetworkVariableWritePermission.Owner
);
private bool _isWeaponEquipped = false;
private float _attackStartTime;
private const float ATTACK_TIMEOUT = 2f; // Auto-reset if animation event doesn't fire
private void Awake()
{
@@ -43,7 +49,7 @@ namespace Northbound
public bool CanExecute(ulong playerId)
{
if (blockDuringAnimation && _isAttacking)
if (blockDuringAnimation && _isAttacking.Value)
return false;
return Time.time - _lastAttackTime >= attackCooldown;
@@ -55,7 +61,10 @@ namespace Northbound
return;
_lastAttackTime = Time.time;
_isAttacking = true;
_attackStartTime = Time.time;
// Owner writes directly (Owner permission on _isAttacking)
_isAttacking.Value = true;
// 장비 장착 (애니메이션 이벤트 사용 안 할 경우)
if (!useAnimationEvents && useEquipment && !_isWeaponEquipped)
@@ -73,7 +82,7 @@ namespace Northbound
if (_animator == null || string.IsNullOrEmpty(attackAnimationTrigger))
{
PerformAttack();
_isAttacking = false;
_isAttacking.Value = false;
}
}
@@ -168,7 +177,10 @@ namespace Northbound
public void OnAttackComplete()
{
_isAttacking = false;
if (IsOwner)
{
_isAttacking.Value = false;
}
if (useEquipment && equipmentData != null && equipmentData.detachOnEnd && !equipmentData.keepEquipped)
{
@@ -183,16 +195,10 @@ namespace Northbound
private void AttachWeapon(string socketName = null)
{
if (_equipmentSocket == null || equipmentData == null)
{
Debug.LogWarning("[AttackAction] EquipmentSocket 또는 EquipmentData가 없습니다.");
return;
}
if (equipmentData.equipmentPrefab == null)
{
Debug.LogWarning("[AttackAction] 무기 프리팹이 설정되지 않았습니다.");
return;
}
string socket = socketName ?? equipmentData.socketName;
_equipmentSocket.AttachToSocket(socket, equipmentData.equipmentPrefab);
@@ -251,6 +257,34 @@ namespace Northbound
Gizmos.DrawWireSphere(attackOrigin, attackRange);
}
public override void OnNetworkSpawn()
{
base.OnNetworkSpawn();
// Subscribe to attack state changes
_isAttacking.OnValueChanged += OnAttackStateChanged;
}
public override void OnNetworkDespawn()
{
_isAttacking.OnValueChanged -= OnAttackStateChanged;
base.OnNetworkDespawn();
}
private void OnAttackStateChanged(bool previousValue, bool newValue)
{
}
public void Update()
{
if (!IsOwner) return;
if (_isAttacking.Value && Time.time - _attackStartTime > ATTACK_TIMEOUT)
{
_isAttacking.Value = false;
}
}
public override void OnDestroy()
{
// 무기 정리
@@ -262,6 +296,6 @@ namespace Northbound
base.OnDestroy();
}
public bool IsAttacking => _isAttacking;
public bool IsAttacking => _isAttacking.Value;
}
}