using Unity.Netcode; using UnityEngine; public class DroppedItem : NetworkBehaviour, IInteractable { [SerializeField] private MeshFilter myFilter; // 자식의 MeshFilter 연결 [SerializeField] private MeshRenderer myRenderer; // 자식의 MeshRenderer 연결 [SerializeField] private float dropScale = 0.3f; private Rigidbody _rb; [SerializeField] private float jumpForce = 5f; // 위로 솟구치는 힘 [SerializeField] private float spreadForce = 2f; // 옆으로 퍼지는 힘 [SerializeField] private float rotationSpeed = 100f; // 빙글빙글 도는 속도 private NetworkVariable _itemDataID = new NetworkVariable(); private bool _isProcessed = false; // 중복 획득 방지 (서버용) private void Awake() { _rb = GetComponent(); } public override void OnNetworkSpawn() { UpdateVisuals(); _itemDataID.OnValueChanged += (oldVal, newVal) => UpdateVisuals(); if (IsServer) { ApplyInitialPop(); } } private void ApplyInitialPop() { // 위쪽 방향 + 무작위 주변 방향으로 힘을 줍니다. Vector3 force = Vector3.up * jumpForce + Random.insideUnitSphere * spreadForce; _rb.AddForce(force, ForceMode.Impulse); // 무작위 회전력(Torque)을 주어 던져지는 느낌을 냅니다. _rb.AddTorque(Random.insideUnitSphere * spreadForce, ForceMode.Impulse); } public void Initialize(int id) { if (IsServer) _itemDataID.Value = id; } private void Update() { // 비주얼만 빙글빙글 돌게 하고 싶다면 (선택 사항) transform.Rotate(Vector3.up * rotationSpeed * Time.deltaTime); } private void UpdateVisuals() { ItemData data = ItemDatabase.Instance.GetItemByID(_itemDataID.Value); if (data != null && data.originalBlockPrefab != null) { // 원본 프리팹(큰 블록)에서 비주얼 컴포넌트를 찾습니다. MeshFilter sourceFilter = data.originalBlockPrefab.GetComponentInChildren(); MeshRenderer sourceRenderer = data.originalBlockPrefab.GetComponentInChildren(); if (sourceFilter != null && myFilter != null) myFilter.sharedMesh = sourceFilter.sharedMesh; if (sourceRenderer != null && myRenderer != null) myRenderer.sharedMaterial = sourceRenderer.sharedMaterial; // 크기를 작게 줄여서 아이템처럼 보이게 합니다. transform.localScale = Vector3.one * dropScale; } } // 플레이어의 OnInteractTap에서 호출될 함수입니다. public void Interact(GameObject interactor) { Debug.Log("[DroppedItem] 상호작용 시도됨"); // 1. 상호작용한 플레이어가 본인(Owner)인지 확인합니다. if (interactor.TryGetComponent(out var playerNetObj) && playerNetObj.IsOwner) { // 2. 서버에 이 아이템을 줍겠다고 요청합니다. RequestPickupServerRpc(playerNetObj.NetworkObjectId); Debug.Log("[DroppedItem] 아이템 획득 요청 서버 RPC 호출됨"); } } [Rpc(SendTo.Server, InvokePermission = RpcInvokePermission.Everyone)] private void RequestPickupServerRpc(ulong playerNetId) { if (_isProcessed) return; // 서버에서 아이템 데이터를 가져오고 플레이어 인벤토리에 추가합니다. if (NetworkManager.Singleton.SpawnManager.SpawnedObjects.TryGetValue(playerNetId, out var playerObj)) { if (playerObj.TryGetComponent(out var inventory)) { _isProcessed = true; ItemData data = ItemDatabase.Instance.GetItemByID(_itemDataID.Value); inventory.AddItem(data); // 인벤토리에 추가 // 3. 획득 성공 시 네트워크 상에서 제거합니다. GetComponent().Despawn(); } } } }