-
Notifications
You must be signed in to change notification settings - Fork 0
Home
Unity Editor allows us to design and create ui objects in any Scene
. These objects need to be placed in a Canvas
component and premade ui elements like Button
and Text
can be created in the active scene. Any MonoBehaviour
object that lives in the scene can be saved as a Prefab
. That allows us to use them in multiple scenes, instantiate in runtime or achieve nested prefabs and variants introduced in 2018.3 version.
This workflow is visually easy to prototype and design. Especially static elements in the scene like a background or a label that sits in the scene. But the dynamic control or runtime manipulation of scene elements via code can be overwhelming. Each element needs to be referenced before the application started from the scene or in the runtime, searching through the scene or any MonoBehaviour
via GetComponent<T>
methods.
public class SomeManager : MonoBehaviour
{
// If your class attached to an object before game started
// your components can be referenced like this from the editor
public Button buttonFromScene;
private void Start()
{
// Find the object int the scene matching exact name
// Get the component via api
Text scoreLabel = GameObject.Find("Score Label").GetComponent<Text>();
}
}
This methodology leads us to create wrapper objects to hold these multiple references to
// It is possible to create a prefab that hold the referances
public class SomeView : MonoBehaviour
{
public Button buttonFromPrefab;
public Text buttonLabel;
public Dropdown optionsDropdown;
}
public class SomeManager : MonoBehaviour
{
...
private void CreateUI()
{
// prefab gameObject could be loaded from Resources
GameObject uiObject = Instantiate(uiPrefab, uiParent);
SomeView ui = uiObject.GetComponent<SomeView>();
ui.buttonLabel.text = "some label";
ui.buttonFromPrefab.onClick.AddListener(SomeMethod);
}
private void SomeMethod()
{
// Do stuff
}
...
}
This example is the way I do most of the time when things get complex but ui programming may gets to complicated when your project grow, as we know, or you may only need a simple structure that only needs a couple of line of work and you don't feel like to hassle with unity ui and editor flow at all.
Another solution would be creation the objects programmatically. Since any component can be added to any GameObject
it is possible to make any remade ui objects that editor provided.
...
GameObject uiObject = new GameObject();
Text label = uiObject.AddComponent<Text>();
label.text = "Hello!";
...
That works but you know that it must be placed in a Canvas
and you would needed more when you make more complex objects like Button
or Dropdown
. Its just a bunch of nested objects and attached components like image, text and button.
This is how I started to create quill. I wanted to create the elements I need in one line without going back and fourth between editor and code, referencing and managing all objects and wrappers, so on. Quill does not try to replace Unity UI. It only provides an api to achieve the programmatic functionality I described above.
Here is the label and button:
public class QuillLabel : Text, IQuillElement
{
...
}
public class QuillButton : Button, IQuillElement
{
...
public QuillLabel label;
public QuillBox box;
...
}
So every quill component is derived from the unity ui class itself. Then you would use the way you use normally.
var label = Quill.CreateLabel("hello world!");
label.fontSize = 20;
var button = Quill.CreateButton("hello button!");
button.onClick.AddListener(SomeMethod);
button.interactable = false;
Also, it exposes c# api to lua (MoonSharp). It will hook up Init
and OnUpdate
functions from main.lua
file.