163 lines
5.6 KiB
C#
163 lines
5.6 KiB
C#
using UnityEngine;
|
|
using System.Collections.Generic;
|
|
using Unity.Netcode;
|
|
|
|
namespace Northbound
|
|
{
|
|
/// <summary>
|
|
/// 네트워크 환경에서 작동하는 장비 소켓 관리
|
|
/// </summary>
|
|
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<Socket> sockets = new List<Socket>();
|
|
|
|
private Dictionary<string, Socket> _socketDict = new Dictionary<string, Socket>();
|
|
|
|
private void Awake()
|
|
{
|
|
// 빠른 검색을 위한 딕셔너리 생성
|
|
foreach (var socket in sockets)
|
|
{
|
|
if (!string.IsNullOrEmpty(socket.socketName))
|
|
{
|
|
_socketDict[socket.socketName] = socket;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 소켓에 장비 부착 (네트워크 스폰)
|
|
/// </summary>
|
|
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<NetworkObject>();
|
|
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($"<color=green>[NetworkEquipmentSocket] 장비 장착됨: {socketName} -> {equipmentPrefab.name}</color>");
|
|
return equipment;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 소켓에서 장비 제거 (네트워크 디스폰)
|
|
/// </summary>
|
|
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($"<color=yellow>[NetworkEquipmentSocket] 장비 제거됨: {socketName}</color>");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 모든 소켓에서 장비 제거
|
|
/// </summary>
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 특정 소켓에 장비가 있는지 확인
|
|
/// </summary>
|
|
public bool HasEquipment(string socketName)
|
|
{
|
|
if (_socketDict.TryGetValue(socketName, out Socket socket))
|
|
{
|
|
return socket.currentEquipment != null;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
}
|