I’m trying to make a multiplayer game using Photon PUN 2 in Unity and I’m pretty new at this. I’m trying to make an inventory system similar to the Lethal Company game, simply I have 4 slots and I can switch between these slots. Whichever slot I am in, I can take an item to that slot and the item appears in my “handPosition” object, and when I change the slot, if the slot I pass through is empty, my hand appears empty even though the item remains on me. Everything is normal so far, but there is a problem, the ownership transfers are working incorrectly. When a player picks up an object, he becomes its owner, but when he drops the object, that player continues to own the object, even though the object should be ownerless. Even he cannot pick up the object he dropped.
This is my script, please help me…
using UnityEngine;
using Photon.Pun;
using UnityEngine.UI;
using System.Collections;
public class InventorySystem : MonoBehaviourPunCallbacks
{
public Transform holdPosition;
public GameObject[] inventorySlots = new GameObject[4];
private int activeSlot = 0;
private GameObject currentHeldObject = null;
public Image[] slotImages;
public Color activeSlotColor = Color.yellow;
public Color defaultSlotColor = Color.white;
void Start()
{
UpdateSlotUI();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.E))
{
if (currentHeldObject == null)
{
TryPickupObject();
}
else
{
DropObject();
}
}
if (Input.GetKeyDown(KeyCode.Alpha1)) { SwitchSlot(0); }
if (Input.GetKeyDown(KeyCode.Alpha2)) { SwitchSlot(1); }
if (Input.GetKeyDown(KeyCode.Alpha3)) { SwitchSlot(2); }
if (Input.GetKeyDown(KeyCode.Alpha4)) { SwitchSlot(3); }
UpdateHeldObject();
}
void TryPickupObject()
{
Collider[] colliders = Physics.OverlapSphere(transform.position, 2f);
foreach (Collider collider in colliders)
{
if (collider.CompareTag("Pickable"))
{
PhotonView objView = collider.GetComponent<PhotonView>();
if (objView != null)
{
if (objView.Owner == null || objView.Owner != PhotonNetwork.LocalPlayer)
{
// Take ownership directly
objView.TransferOwnership(PhotonNetwork.LocalPlayer);
StartCoroutine(WaitForOwnership(objView, collider.gameObject));
break;
}
}
}
}
}
IEnumerator WaitForOwnership(PhotonView objView, GameObject obj)
{
while (objView.Owner != PhotonNetwork.LocalPlayer)
{
yield return null;
}
AddToInventory(obj);
photonView.RPC("SyncPickupObject", RpcTarget.Others, objView.ViewID, activeSlot);
}
[PunRPC]
void SyncPickupObject(int viewID, int slotIndex)
{
PhotonView objView = PhotonView.Find(viewID);
GameObject obj = objView.gameObject;
inventorySlots[slotIndex] = obj;
obj.SetActive(false);
}
void AddToInventory(GameObject obj)
{
if (inventorySlots[activeSlot] == null)
{
inventorySlots[activeSlot] = obj;
obj.SetActive(false);
}
}
void DropObject()
{
if (currentHeldObject != null)
{
GameObject obj = currentHeldObject;
PhotonView objView = obj.GetComponent<PhotonView>();
if (objView.IsMine)
{
Vector3 dropPosition = GetGroundPosition();
obj.transform.position = dropPosition;
obj.SetActive(true);
currentHeldObject = null;
inventorySlots[activeSlot] = null;
// Remove ownership from the player
objView.TransferOwnership(0); // Set to 0 to make it neutral
photonView.RPC("SyncDropObject", RpcTarget.Others, objView.ViewID, dropPosition);
UpdateSlotUI();
}
}
}
[PunRPC]
void SyncDropObject(int viewID, Vector3 dropPosition)
{
PhotonView objView = PhotonView.Find(viewID);
GameObject obj = objView.gameObject;
obj.transform.position = dropPosition;
obj.SetActive(true);
// Ensure the ownership is neutral when syncing drop
objView.TransferOwnership(0);
}
Vector3 GetGroundPosition()
{
RaycastHit hit;
if (Physics.Raycast(transform.position + Vector3.up, transform.forward, out hit, 3f))
{
return hit.point;
}
else
{
return transform.position + transform.forward * 2f;
}
}
void SwitchSlot(int slotIndex)
{
activeSlot = slotIndex;
UpdateSlotUI();
photonView.RPC("SyncSlotSwitch", RpcTarget.Others, activeSlot);
}
[PunRPC]
void SyncSlotSwitch(int slotIndex)
{
activeSlot = slotIndex;
UpdateSlotUI();
}
void UpdateHeldObject()
{
if (inventorySlots[activeSlot] != null)
{
currentHeldObject = inventorySlots[activeSlot];
currentHeldObject.transform.position = holdPosition.position;
currentHeldObject.transform.rotation = holdPosition.rotation;
currentHeldObject.SetActive(true);
}
else
{
if (currentHeldObject != null)
{
currentHeldObject.SetActive(false);
currentHeldObject = null;
}
}
}
void UpdateSlotUI()
{
for (int i = 0; i < slotImages.Length; i++)
{
slotImages[i].color = (i == activeSlot) ? activeSlotColor : defaultSlotColor;
}
}
}