I’m making a runtime UI, and I’m currently trying to build a setup screen for a multiplayer game. I was hoping to build a UI where I can have buttons provide feedback during long network operations. For example, I have a ‘connect’ button, that will try to reach a server within a certain number of retries, that will show a ‘busy’ spinner while the operation is running.
I have achieved the desired behavior within one UI document, but the logic that controls this faux animation, sits on the script that manages the document, and not the button.
My goal was to create a custom button in code, using a C# script that inherits from Button and write the logic in there. I think I’ve got the logic down (so far, I’ve just exposed an Action which happens when the button is pressed), but I can’t seem to expose the child VisualElement that contains the animated portion of the control. I wanted to be able to re-use this button in the UIBuilder, and have the spinner element exposed, so that it could be swapped out for different use-cases, but all the children elements that are created in C#, are greyed out in the builder.
I have two questions:
Is it possible to do what I want with UI Toolkit?
Is the behavior of not being able to modify the properties of code-created children, by design?
I think you’re being far too tightly coupled to the details of Unity’s UI stuff, like Button and whatnot.
Instead, divorce the input and presentation from the controller logic entirely.
For UnityEngine.UI I wrote a package called Datasacks which lets you decorate any UI with a series of small scripts that interoperate with “datasacks,” which are ScriptableObjects used for transferring data and signaling.
For your problem I would use the built-in UserIntent datasack for all inputs (that is almost always sufficient), and for the output you might need to signal a few things:
disable / enable the animation spinner
disable / enable the button
show some text perhaps?
Keep EVERYTHING logic-wise out of your UI … that way in the future if you change platforms you can trivially swap out the UI and the business logic never even knows, because it is hitting on datasacks (or your own notion of such a break-out system).
The UI builder is just a representation as to what the UI would look like once constructed. If you have UXML factory exposed visual elements that generate child elements, these don’t actually ‘exist’ at the time of the UI builder so they can’t be edited.
You could of course expose an image/sprite field with UXML in the button class itself, that it passes through to the child.
This was something I was also looking to do, but I wasn’t entirely sure how to get it to work.
I can see the existing cursor image, and background image fields have buttons to choose which asset you want, but I couldn’t see how to get the same functionality in this instance?