-
Notifications
You must be signed in to change notification settings - Fork 14
Note
You don't need to use Image/RawImage/Text/TMP*/Button/etc references to control their states. UIWS has component containers for each type as a replacement.
Note
WindowSystem and ListComponent have a Closure API call which allows to pass some data without allocation.
// show MyScreen in asynchronous mode
WindowHandler<MyScreen> screenHandle = WindowSystem.Show<MyScreen>();
// show MyScreen immediately and return it's instance
MyScreen screenInstance = WindowSystem.ShowSync<MyScreen>();
// show MyScreen in asynchronous mode and pass some parameters to the OnParametersPass method
WindowHandler<MyScreen> screenHandle = WindowSystem.Closure(someData).Show<MyScreen>(static (w, data) => w.OnParametersPass(data)); // Send data to all opened screens and their components
WindowSystem.SendEvent(T data);
// Register object state once (will be automatically unregistered if fires
WindowSystem.RegisterActionOnce(TState state, WindowObject instance, WindowEvent windowEvent, System.Action<WindowObject, TState> callback);
// Register object state
WindowSystem.RegisterAction(TState state, WindowObject instance, WindowEvent windowEvent, System.Action<WindowObject, TState> callback);
// Unregister object state
WindowSystem.UnRegisterAction(TState state, WindowObject instance, WindowEvent windowEvent, System.Action<WindowObject, TState> callback);YourComponent -> WindowComponent -> WindowObject -> MonoBehaviour
YourScreen -> LayoutWindowType -> WindowBase -> WindowObject -> MonoBehaviour
WindowLayoutElement -> WindowComponent -> WindowObject -> MonoBehaviour
WindowLayout -> WindowObject -> MonoBehaviour
YourWindowModule -> WindowModule -> WindowLayout -> WindowObject -> MonoBehaviour
YourComponentModule -> *ComponentModule -> WindowComponentModule -> MonoBehaviour
YourComponentModule -> WindowComponentModule -> MonoBehaviour
YourScreen
├── WindowLayout
│ ├── WindowLayoutElement #1
│ │ └── WindowComponent
│ └── WindowLayoutElement #2
│ └── WindowComponent
│ ├── TextComponent
│ └── ImageComponent
├── WindowModule #1
└── WindowModule #2
Separate prefabs:
YourScreen - your screen prefab with Camera (if you use overlay mode - camera will be disabled)
WindowLayout - your layout prefab (Canvas component placed here and safe area settings)
-- WindowLayoutElement #1 - layout element component (WindowLayoutElement component)
-- WindowLayoutElement #2
WindowComponent - your component (basically you can use WindowComponent or any other component if you need that)
-- TextComponent - your text component
-- ImageComponent - your image component
WindowModule - your screen module prefab (you can use any other WindowModule component here), Canvas component is required here
-- WindowComponent - window module can store links to any window components inside
Each WindowObject has a state (ObjectState):
Object State |
Description |
|---|---|
| NotInitialized | Object is not initialized (valid for prefab or if it's hidden by default) |
| Initializing | Object is in initializing state (Show API just called) |
| Loading | If it is require - loading states will be used |
| Loaded | When object loading is complete - this state will be applied |
| Initialized | After object loads - object has become initialized |
| Showing | Start showing animations for all children object |
| Shown | All children object animations are completed |
| Hiding | Hide API just called and all animations for children has been started |
| Hidden | Object becomes hidden after all animations has been completed |
| DeInitializing | When Hide API completes - UIWS will determine what to do with the object, if it must be pooled - object leaves in Hidden state, otherwise object starts de-initialization (Unity Destroy analogy) |
| DeInitialized | When all de-initialization jobs are done |
Method |
Description |
|---|---|
| OnInit | When object OnInitialized state applied. It's called once for the new object instance. |
| OnDeInit | When object will be destroyed from scene |
| OnShowBegin | Show API called. Animation has been started for current object |
| OnShowEnd | Animation has beed complete for current object and all children |
| OnHideBegin | Hide API called. Animation has been started for current object |
| OnHideEnd | Animation has beed complete for current object and all children |
| OnFocusTook | When focus on window is returned back or new window is shown at the top of others |
| OnFocusLost | When focus on window is lost |
| OnLayoutReady | When layout is ready. Here you can use uGUI layout object size or position |
| OnPoolGet | Object was in pool and now used |
| OnPoolAdd | Object needs to be pooled and Hidden state is applied |
| OnEvent(T) | WindowSystem.SendEvent has been called with the custom data |
Important
Do not use gameObject.SetActive API with a UIWS components
// Show component (like a gameObject.SetActive(true), but with animations and right FSM state)
component.Show();
// Hide component (like a gameObject.SetActive(false), but with animations and right FSM state)
component.Hide();
// Show or hide component depends on boolean state
component.ShowHide(bool);
// Check component is visible in hierarchy
component.IsVisible();
// Check component is visible self
component.IsVisibleSelf();There are a lot of default components implemented, here are some common cases which may be useful:
// set text
textComponent.SetText("some text");
// set unity localization
textComponent.SetText(unityLocalizationKey);
// set unity localization with parameters
textComponent.SetText(unityLocalizationKey, param1, param2, ...);
// set double value
textComponent.SetValue(123);
// set text with some int values (there are various overloads for these format)
textComponent.SetText(10, "/", 100);| Method | Description |
|---|---|
SetValueFormat(ITextFormatter, string) |
Set custom value formatter |
SetValue(double) |
Set value as text |
SetValue(double, SourceValue) |
Set value as text and format it with SourceValue |
SetValue(double, SourceValue.Seconds, [normal] TimeResult, [short] TimeResult) |
Set value as a time between short and normal variants (depends on value) |
SetColor |
Set color to the UGUI Text or TMP Text color field |
| SourceValue | Description |
|---|---|
SourceValue.Digits |
Default value formatted with InvariantCulture or custom text formatter if applied |
SourceValue.Seconds |
Format with default time format in seconds |
SourceValue.Milliseconds |
Format with default time format in milliseconds |
SourceValue.Percent |
Add percent char at the end of the value (ex: 15%) with InvariantCulture |
// replace button callback with new SomeMethod call
// you don't need to unregister this callback because it will be managed automatically
buttonComponent.SetCallback(SomeMethod);
// or you can use closure-free method to avoid unnecessary allocations
buttonComponent.SetCallback(closureState, static (data) => ...);
// set interactable button state
buttonComponent.SetInteractable(state);
// ButtonComponent has an inheritance from GenericComponent,
// so you can use GenericComponent's Get<>() method to get children components
buttonComponent.Get<TextComponent>().SetText(...)
// rarely you need to use these methods if you really need to control multiple callbacks
buttonComponent.AddCallback(...)
buttonComponent.RemoveCallback(...)| Method | Description |
|---|---|
SetInteractable |
Set button interactable state |
SetCallback(TState, (TState) => ...) |
Replace button callback with zero-allocation method |
SetCallback(() => ...) |
Replace button callback |
AddCallback(() => ...) |
Add button callback |
RemoveCallback(() => ...) |
Remove button callback |
// set sprite
imageComponent.SetImage(sprite);
// set texture
imageComponent.SetImage(texture2d);
// set Resource (or Resource<>) which will be loaded by built-in UIWS Resources system
// it is the better type of SetImage call because it will handles Load/Unload AssetBundles/Addressables automatically
imageComponent.SetImage(resource);| Method | Description |
|---|---|
SetMaterial |
Set material instance to the UGUI Image/RawImage |
SetFillAmount |
Set fill amount to the UGUI Image fillAmount field |
SetColor |
Set color to the UGUI Image/RawImage color field |
SetImage(Sprite) |
Set sprite to Image |
SetImage(Texture2D) |
Set texture to RawImage |
SetImage(Resource) |
Set custom resource as sprite or texture |
// default usage
var arr = new SomeData[...];
listComponent.SetItems(arr.Length, (item, parameters) => {
// item is a view instance
item.SetInfo(arr[parameters.index]);
});
// set without allocations
var arr = new SomeData[...];
listComponent.Closure((arr, someData: 123)).SetItems(arr.Length, static (item, parameters) => {
// item is a view instance
item.SetInfo(parameters.data.arr[parameters.index], parameters.data.someData);
});
// list fill is async, so we may have to use complete callback
var arr = new SomeData[...];
listComponent.SetItems(arr.Length, (item, parameters) => {
...
}, (parameters, result) => {
// result is TRUE if list is complete and FALSE if it's not ready yet
// for example, if we call SetItems in Update method - we will get result as FALSE for a few frames and then TRUE when the job is done
});| Method | Description |
|---|---|
SetItems |
Set items from your data source |
Clear |
Remove all list items |
AddItem |
Add custom source item |
GetItem |
Return item by index in visible items list |
You can add custom modules for components where you can handle or change default component behavior. For example: if you want to format text or value in TextComponent, you can add module which overrides set text method.
You can add custom modules for screens to add some common layout things like a player resource panel, or add some common behavior like a back button or close background behavior.
Add UNITY_URP to project defines
Add URP Module module to WindowSystem initializer
public class MyScreen : LayoutWindowType {
private TextComponent text1Component;
private TextComponent text2Component;
private ButtonComponent someButton;
private System.Action onButtonClick;
public void OnParametersPass(System.Action onButtonClick) {
this.onButtonClick = onButtonClick;
}
// fires on first instance only (if there is no instance in the pool)
public override void OnInit() {
base.OnInit();
this.GetLayoutComponent(out this.text1Component); // get first text component assigned on the screen instance
this.GetLayoutComponent(out this.text2Component); // get next text component (this behavior by default)
this.GetLayoutComponent(out this.someButton); // get first button component
}
// fires on each instance before animations has been started
public override void OnShowBegin() {
base.OnShowBegin();
this.SetInfo();
}
// set some info
public void SetInfo() {
this.text1Component.SetText("Sample text1");
this.text2Component.SetText("Sample text2");
// here we use closure to set up callback without allocations
this.someButton.SetCallback(this.onButtonClick, static (cbk) => cbk.Invoke());
// here is text set sample to the button instance
// be sure that you have components array fill in the inspector
this.someButton.Get<TextComponent>().SetText("Button text");
}
}