Best practice for item pick ups and split screen

splinedrew

New member
I'm wondering what the best practice would be for setting up Item Pick Ups in a split screen style game.

Say there are 2 players in a left screen/right screen game. Say Player 1 drops an item from their inventory. Now when player 1 or player 2 walk up to the interactable, the Pick Up Canvas is displayed. The problem is the pick up canvas is displayed on both players screens, but only oriented to Camera.main per the BillboardFx script. I can make my own billboarding script to select a specific camera to look at, but how do I know which player is the current user/owner of that interactable? The other thing I would have to take into account is setting up the Layers the PickUpCanvas is on so that it only displays to the camera that is the owner of the interactable. I guess I am just wondering if anyone has some insight on the best approach to this and how to determine the current owner of the interactable.

Thanks!
 

Sangemdoko

Moderator
Staff member
I think your approach makes sense. You simply need to make a custom pickup that would have two canvases. Then override the functionality that shows the canvas and check what inventory is trying to interact with the pickup. The pickups should know what Inventory is trying to interact with them because they need to know where the items should be added.

You always have the choice to create completely custom Item Pickups which gives you complete control, but for this use case simply making a custom pickup inheriting the basic pickup should do the trick
 

splinedrew

New member
Thanks for the help! So this is what I ended up going with and it seems to work pretty well so far.

C#:
namespace Opsive.UltimateInventorySystem.DropsAndPickups
{
    using UnityEngine;
    using Opsive.UltimateInventorySystem.Interactions;
    using Opsive.UltimateInventorySystem.Core.InventoryCollections;

    public class ItemPickUpSplitscreen : ItemPickup
    {
        [SerializeField] internal GameObject[] m_Player1Indicators;
        [SerializeField] internal GameObject[] m_Player2Indicators;

        public override void OnSelect(IInteractor interactor)
        {
            base.OnSelect(interactor);
            if (interactor == null) { return; }
            if (!(interactor is IInteractorWithInventory interactorWithInventory)) { return; }
            if (interactorWithInventory.Inventory.TryGetComponent(out InventoryIdentifier Identifier))
            {
                switch (Identifier.ID)
                {
                    case 1:
                        for (int i = 0; i < m_Player1Indicators.Length; i++) { m_Player1Indicators[i].SetActive(true); }
                        break;
                    case 2:
                        for (int i = 0; i < m_Player2Indicators.Length; i++) { m_Player2Indicators[i].SetActive(true); }
                        break;
                }
            }
        }

        public override void OnDeselect(IInteractor interactor)
        {
            base.OnDeselect(interactor);
            if (interactor == null) { return; }
            if (!(interactor is IInteractorWithInventory interactorWithInventory)) { return; }
            if (interactorWithInventory.Inventory.TryGetComponent(out InventoryIdentifier Identifier))
            {
                switch (Identifier.ID)
                {
                    case 1:
                        for (int i = 0; i < m_Player1Indicators.Length; i++) { m_Player1Indicators[i].SetActive(false); }
                        break;
                    case 2:
                        for (int i = 0; i < m_Player2Indicators.Length; i++) { m_Player2Indicators[i].SetActive(false); }
                        break;
                }
            }
        }
    }
}

Because I have 2 pick up canvas's I also needed a way to set up the visual components correctly for both of them. I ended up writing this helper script to go along with the pick up prefabs.

C#:
namespace Opsive.UltimateInventorySystem.DropsAndPickups
{
    using Opsive.UltimateInventorySystem.Core.DataStructures;
    using Opsive.UltimateInventorySystem.UI.Item.ItemViewModules;
    using UnityEngine;

    public class ItemObjectVisualizerSplitscreen : ItemObjectVisualizer
    {
        [Tooltip("The second players item view")]
        [SerializeField] protected ItemView m_ItemView_P2;

        protected override void UpdateItemView(ItemInfo itemInfo)
        {
         
            if (m_ItemView)
            {
                m_ItemView.SetValue(itemInfo);
            }
            if (m_ItemView_P2)
            {
                m_ItemView_P2.SetValue(itemInfo);
            }        
        }
    }
}

Lastly, I rewrote a new billboarding script that looked at either p1 or p2 camera instead of Camera.main. This was pretty straight forward so I didn't bother pasting the code.

I also created new scripts for InventoryPickUp and RandomInventoryPickUp which look pretty similar to ItemPickUpSplitscreen I posted above.

Hopefully this helps someone, and if there is a better or cleaner approach I'd be happy to hear it!
 
Top