1
\$\begingroup\$

I have a Canvas that has multiple UI Panels in it for an inventory, crafting, etc. To open these panels I currently have a monobehaviour class on the Canvas with methods like OpenInventory(), etc.

For every item within the inventory I use ScriptableObjects. However, some items open the crafting panel when right clicking, I created a class that extends the Item class and added a method to it that gets added to the inventory slot and gets called when right clicking that item.

Because the monobehaviour on the Canvas is an instance, I can't access it from a ScriptableObject.

Long story short, is there a way to open a UI panel from a ScriptableObject? If not, what would be the best way to fix this issue?

\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

Bad solution:

  • Add to ScriptableObject public field of type Canvas (better - private field with public setter).
  • On Monobehaviour's Awake() write current canvas' reference to ScriptableObject.
  • Now you can call canvas from ScriptableObject! Any new canvas on Awake() automatically overwrites reference to itself so you always get actual canvas.

Kinda bad solution:

Transform canvas into Singleton. Or, better, create a whole UI manager as Singleton with link to Canvas in question. Then you could access any UI window like this:

UiManager.Instance.OpenInventory();

or:

UiManager.Instance.Inventory.Show();

Nice solution:

You are calling a method inside ScriptableObject from somewhere, right? Could you pass reference to Canvas as method parameter? Or maybe you could wrap the whole method and pass it as delegate?

Another option is to make use of UnityEvent system or create your own event-based system (which is extremely helpful while you trying to pass data between separate modules). In that case you can achieve anything using some creative subscriptions/event triggering.

\$\endgroup\$
1
\$\begingroup\$

You can tag the Canvas (for example with the tag "Menu") and then in your scriptable object do a GameObject.FindGameObjectWithTag("Menu") and then you can call the method via GetComponent<...>().OpenCraftingPanel()

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .