I don’t like the concept of a bunch of pickups being scattered across the level/enemies dropping physical items, so I want to implement this via loot, i.e. the player clicks on a chest/designated container or a dead enemy, and a panel opens up with UI representations of items and the player clicks on them to add them to the inventory, like here:
(Of course, mine looks way simpler )
I kept the course’s way of picking up items too, because it’s necessary for when the player wants to pick up an item he’s previously dropped from the inventory. I can share the entire thing once it’s done, but for now I’ll just summarize the system to get to the question.
I have introduced a new interface called ICollectable which is implemented by Pickup and my new Loot class:
public interface ICollectable
{
void HandleCollection();
Transform GetTransform();
}
These are used by the Collector class which previously only handled pickups.
Loot class is supposed to be working similarly to Inventory, but it is placed on containers with items instead of on the player. It implements IRaycastable, which looks like this:
public bool HandleRaycast(PlayerController callingController)
{
if (Input.GetMouseButtonDown(0))
{
callingController.GetComponent<Collector>().Collect(this);
if (!_filled)
FillLoot();
}
return true;
}
_filled flag is checked once the loot object is clicked for the first time because I don’t want the game to fill the loot which is never clicked on. FillLoot()
fills the loot with random items and uses DropLibrary
to do that, the same way it’s done in RandomDropper
.
Now, when the loot object/container is clicked it is supposed to fire off an event which is subscribed to by the loot UI: public static event Action<Loot> OnLootClicked;
.
This is where I stumble for some reason.
LootUI subscribes to this event in OnEnable and then deactivates the loot panel in Start:
void OnEnable()
{
Loot.OnLootClicked += OpenLootPanel;
}
void Start()
{
_lootPanel.SetActive(false);
}
Then, OpenLootPanel should set up the loot, but it’s behaving strangely:
void OpenLootPanel(Loot loot)
{
_lootPanel.SetActive(true);
_loot = loot;
Debug.Log(_loot.gameObject.name);
}
I’ve put the LootUI script on a canvas, and the _lootPanel is its child.
But when I click on the container (Pickup Pot object), I get an error “MissingReferenceException: The object of type 'GameObject' has been destroyed but you are still trying to access it.
”
So I put the null check in OpenLootPanel
void OpenLootPanel(Loot loot)
{
if (_lootPanel == null)
{
Debug.Log("Loot panel not set.");
return;
}
_lootPanel.SetActive(true);
_loot = loot;
Debug.Log(_loot.gameObject.name);
}
and now it does everything: it displays the log message “Loot panel not set
” as if the panel is null, then skips the return, then the panel somehow becomes not null again and it gets set to active and the rest of the method executes. Why and how is this happening?
I’ve checked and the panel is not null after it gets deactivated in Start()
. It’s only null right when the method OpenLootPanel
is called, then becomes not null again after the null check in that method.
(I know it was a lot of explaining for something I’m sure will turn out to be something basic, but I’ll probably have more questions as I try to implement this so I’ll use this thread if it happens.)