using UnityEngine; using System.Collections.Generic; using Unity.Netcode; namespace Northbound { /// /// 네트워크 환경에서 작동하는 장비 소켓 관리 /// public class NetworkEquipmentSocket : NetworkBehaviour { [System.Serializable] public class Socket { public string socketName; // "RightHand", "LeftHand", "Back" 등 public Transform socketTransform; // 실제 본 Transform [HideInInspector] public NetworkObject currentEquipmentNetworkObj; // 현재 장착된 장비 NetworkObject [HideInInspector] public GameObject currentEquipment; // 현재 장착된 장비 GameObject } [Header("Available Sockets")] public List sockets = new List(); private Dictionary _socketDict = new Dictionary(); private void Awake() { // 빠른 검색을 위한 딕셔너리 생성 foreach (var socket in sockets) { if (!string.IsNullOrEmpty(socket.socketName)) { _socketDict[socket.socketName] = socket; } } } /// /// 소켓에 장비 부착 (네트워크 스폰) /// public GameObject AttachToSocket(string socketName, GameObject equipmentPrefab) { if (!IsServer) { Debug.LogWarning("[NetworkEquipmentSocket] 서버에서만 장비를 장착할 수 있습니다."); return null; } if (!_socketDict.TryGetValue(socketName, out Socket socket)) { Debug.LogWarning($"[NetworkEquipmentSocket] 소켓을 찾을 수 없습니다: {socketName}"); return null; } if (socket.socketTransform == null) { Debug.LogWarning($"[NetworkEquipmentSocket] 소켓 Transform이 없습니다: {socketName}"); return null; } // 기존 장비 제거 DetachFromSocket(socketName); // 새 장비 생성 if (equipmentPrefab != null) { GameObject equipment = Instantiate(equipmentPrefab, socket.socketTransform); equipment.transform.localPosition = Vector3.zero; equipment.transform.localRotation = Quaternion.identity; // NetworkObject 확인 NetworkObject netObj = equipment.GetComponent(); if (netObj == null) { Debug.LogWarning($"[NetworkEquipmentSocket] 장비 프리팹에 NetworkObject가 없습니다: {equipmentPrefab.name}"); Destroy(equipment); return null; } // 네트워크에 스폰 netObj.Spawn(true); // true = 소유자가 파괴되면 장비도 파괴 socket.currentEquipment = equipment; socket.currentEquipmentNetworkObj = netObj; Debug.Log($"[NetworkEquipmentSocket] 장비 장착됨: {socketName} -> {equipmentPrefab.name}"); return equipment; } return null; } /// /// 소켓에서 장비 제거 (네트워크 디스폰) /// public void DetachFromSocket(string socketName) { if (!IsServer) { Debug.LogWarning("[NetworkEquipmentSocket] 서버에서만 장비를 제거할 수 있습니다."); return; } if (!_socketDict.TryGetValue(socketName, out Socket socket)) return; if (socket.currentEquipment != null) { // 네트워크에서 디스폰 if (socket.currentEquipmentNetworkObj != null && socket.currentEquipmentNetworkObj.IsSpawned) { socket.currentEquipmentNetworkObj.Despawn(true); } // 로컬 파괴 if (socket.currentEquipment != null) { Destroy(socket.currentEquipment); } socket.currentEquipment = null; socket.currentEquipmentNetworkObj = null; Debug.Log($"[NetworkEquipmentSocket] 장비 제거됨: {socketName}"); } } /// /// 모든 소켓에서 장비 제거 /// public void DetachAll() { if (!IsServer) return; foreach (var socket in sockets) { if (socket.currentEquipment != null) { if (socket.currentEquipmentNetworkObj != null && socket.currentEquipmentNetworkObj.IsSpawned) { socket.currentEquipmentNetworkObj.Despawn(true); } Destroy(socket.currentEquipment); socket.currentEquipment = null; socket.currentEquipmentNetworkObj = null; } } } /// /// 특정 소켓에 장비가 있는지 확인 /// public bool HasEquipment(string socketName) { if (_socketDict.TryGetValue(socketName, out Socket socket)) { return socket.currentEquipment != null; } return false; } } }