Предметы работают только для основного игрока, а не для клиентского игрока
В моей многопользовательской игре система предметов идеально работает для основного игрока. Однако у меня возникли проблемы с клиентским проигрывателем. В частности:
Предметы, которые подбирает клиент, не отображаются в его руке, а добавляются в инвентарь.
клиент не может удалить элементы.
Клиент не может видеть, какие элементы удалил хост.
У меня есть реализовал систему инвентаризации с помощью Unity Netcode, но похоже, что синхронизация у клиента работает некорректно. Что может быть причиной этих проблем и как я могу обеспечить правильную синхронизацию получения и падения предметов между хостом и клиентскими игроками? Мы будем очень признательны за любые рекомендации и предложения! Скрипт PlayerInventory
using UnityEngine;
using Unity.Netcode;
public class Item : NetworkBehaviour
{
public string itemName;
public override void OnNetworkSpawn()
{
if (IsServer)
{
//
}
}
}
Я потратил немало времени, пытаясь устранить и решить эту проблему, но не смог найти решения. Я несколько раз проверял свой код и настройки сети, но проблема не устранена.
[b]Предметы работают только для основного игрока, а не для клиентского игрока[/b] В моей многопользовательской игре система предметов идеально работает для основного игрока. Однако у меня возникли проблемы с клиентским проигрывателем. В частности: [list] [*]Предметы, которые подбирает клиент, не отображаются в его руке, а добавляются в инвентарь. [*] клиент не может удалить элементы. [*]Клиент не может видеть, какие элементы удалил хост. [/list] У меня есть реализовал систему инвентаризации с помощью Unity Netcode, но похоже, что синхронизация у клиента работает некорректно. Что может быть причиной этих проблем и как я могу обеспечить правильную синхронизацию получения и падения предметов между хостом и клиентскими игроками? Мы будем очень признательны за любые рекомендации и предложения! [b]Скрипт PlayerInventory[/b] [code]using System.Collections.Generic; using UnityEngine; using Unity.Netcode; using TMPro;
public class PlayerInventory : NetworkBehaviour { public List allItems; public List collectedItems = new List(); private int currentItemIndex = -1; private const int maxInventorySlots = 3; public Transform dropPosition;
public override void OnNetworkSpawn() { foreach (GameObject item in allItems) { item.SetActive(false); } }
[ServerRpc(RequireOwnership = false)] public void AddItemToInventoryServerRpc(string itemName, ulong networkObjectId, ServerRpcParams rpcParams = default) { Debug.Log($"Попытка добавить предмет {itemName} в инвентарь на сервере."); if (collectedItems.Count < maxInventorySlots) { GameObject itemToActivate = allItems.Find(item => item.name == itemName); if (itemToActivate != null) { collectedItems.Add(itemToActivate); HideItemForAllClientsClientRpc(itemName); ActivateItemClientRpc(collectedItems.Count - 1); SyncItemInHandClientRpc(itemName, true); RemoveItemFromWorldClientRpc(networkObjectId); Debug.Log($"Предмет {itemName} успешно добавлен в инвентарь."); } else { Debug.LogError($"Предмет {itemName} не найден среди скрытых предметов."); } } else { Debug.Log("Инвентарь полон!"); } }
[ClientRpc] void RemoveItemFromWorldClientRpc(ulong networkObjectId) { if (NetworkManager.Singleton.SpawnManager.SpawnedObjects.TryGetValue(networkObjectId, out NetworkObject networkObject)) { GameObject itemObject = networkObject.gameObject; itemObject.SetActive(false); Destroy(itemObject); } }
public class PlayerInteract : NetworkBehaviour { public float interactionRange = 3f; public Camera playerCamera; public GameObject interactUI; private TMP_Text interactText; private Item itemInFocus; private PlayerInventory playerInventory;
private void Start() { if (interactUI != null) { interactText = interactUI.GetComponent(); if (interactText == null) { Debug.LogError("TMP_Text компонент не найден на interactUI объекте!"); } } else { Debug.LogError("interactUI объект не присвоен в инспекторе!"); }
playerInventory = GetComponent(); }
private void Update() { if (!IsOwner) return;
Ray ray = playerCamera.ScreenPointToRay(new Vector3(Screen.width / 2, Screen.height / 2)); RaycastHit hit;
if (Physics.Raycast(ray, out hit, interactionRange)) { Item item = hit.collider.GetComponent(); if (item != null) { itemInFocus = item; ShowItemInfo(item); if (Input.GetKeyDown(KeyCode.E)) { Debug.Log("Нажата клавиша E для подбора предмета: " + item.itemName); PickupItemServerRpc(item.NetworkObjectId); } } else { HideItemInfo(); } } else { HideItemInfo(); } }
void ShowItemInfo(Item item) { if (interactText != null) { interactUI.SetActive(true); interactText.text = $"Нажмите E, чтобы подобрать {item.itemName}"; } }
[ServerRpc] void PickupItemServerRpc(ulong itemId) { Debug.Log("ServerRpc вызван для предмета с ID: " + itemId); if (NetworkManager.Singleton.SpawnManager.SpawnedObjects.TryGetValue(itemId, out NetworkObject networkObject)) { Item item = networkObject.GetComponent(); if (item != null) { playerInventory.AddItemToInventoryServerRpc(item.itemName, itemId); Debug.Log("Предмет успешно добавлен в инвентарь и удален из мира."); } else { Debug.LogError("Item не найден на объекте NetworkObject!"); } } else { Debug.LogError("NetworkObject с данным itemId не найден!"); } } } [/code] [b]Скрипт элемента[/b] [code]using UnityEngine; using Unity.Netcode;
public class Item : NetworkBehaviour { public string itemName;
public override void OnNetworkSpawn() { if (IsServer) { // }
}
} [/code] Я потратил немало времени, пытаясь устранить и решить эту проблему, но не смог найти решения. Я несколько раз проверял свой код и настройки сети, но проблема не устранена.