How do you separate UI elements , say button into a self contained prefab without references to other game objects?
What I have is a custom Event system , each time button pressed the event is invoked. This way I can keep button as a prefab and it is references only itself.
But this creates a problem, for each button in the scene which does deferent things I will have to create a new event and a new button script
I don’t have many buttons, but still.
Is there a way around it?
This a script on my button:
ublic class UiOnButtonPressed : MonoBehaviour
{
public Button button;
private void Start()
{
button.onClick.AddListener(OnButtonPressed);
}
public void OnButtonPressed()
{
Events.onButtonPressed.Invoke();
}
}
So I’m assuming by event system you mean your own custom event solution and not the UI/Unity version of the EventSystem.
I’ve personally never needed to create individual button prefabs that I instantiate at runtime, ever, not even when working on my 4X game. All my screens/windows are one prefab. I would have your buttons call functions on those root screen/window scripts that invoke the proper events for you. That way you only have one point of external communication between your systems. So the regular built-in Unity Button would invoke void PlayerPurchasedItem() on the ShopWindow, and the ShopWindow would interact with your custom Events systems to invoke the more “global” event of purchasing an item, for example.
I also use scriptable objects as event containers, that way I can drag and drop them right in the inspector to create lines of communication without having to have some global “event manager”, which usually ends up far too bloated and spaghetti strewn throughout your entire code base. Something like this:
[CreateAssetMenu( ... )]
public sealed class ItemEvent : ScriptableObject
{
public Action<Item> onInvoked;
public void Invoke(Item value)
{
if (onInvoked != null)
onInvoked(value);
}
}
Then you can create a new ItemEvent SO named PlayerPurchasedItem in your project, and link that around to all your various scripts.
This is interesting.
So each button within one window has a reference to the window it belongs?
Yes, I have my own simple static Event System class where I have all events. I can see how it might become overloaded as I move forward.
But using the SO for events in the inspector is basically the same (correct me if I am wrong). You will ended up with lots of events in your asset folder.
But grouping buttons into windows/ screens is a good idea
Not really a reference, in the traditional sense, just the appropriate function added to the Button’s OnClick in the inspector.
I’d rather have lots of assets in the project with clean code, then a huge web of references to a global event manager. Just like I’d rather have ten scripts with one singular purpose than one script handling ten purposes.
Personally I really hate the standard Unity pattern of every custom controller in your project requiring really special connections into UI and buttons and text fields and whatnot. It’s a nightmare to maintain and so fragile, and when it breaks you have to laboriously track it down. “Wait, what is this GameObject called Text (2)… oh , that’s the score output… no wait, that’s the WAVE output!”. etc.
NIGHTMARE.
Instead, I favor the approach of bringing all the UI down to code in a totally generic but named fashion, then writing the code to transact against those generic named data items. My package to do this is called Datasacks and here is how it is architected, broadly.