Skip to content

Instantly share code, notes, and snippets.

@LeMartinParadis
Last active May 14, 2024 05:52
Show Gist options
  • Save LeMartinParadis/980041fa7a46846ef8cb9469372e6c22 to your computer and use it in GitHub Desktop.
Save LeMartinParadis/980041fa7a46846ef8cb9469372e6c22 to your computer and use it in GitHub Desktop.
Part 5: Tips & performance considerations.

This is the fifth part in the series: UI Toolkit runtime bindings system

This part will provide some insights that will help you get the most performance when using the UI Toolkit runtime bindings system.

Tips And Performance Considerations

Your own Bindings Types

  • Avoid adding per-element state to your own binding types.
  • When your binding type should only be updated when a change is detected in the source, be sure to set the updateTrigger to BindingUpdateTrigger.OnSourceChanged.
  • When your binding type should only be updated manually, be sure to set the updateTrigger to BindingUpdateTrigger.WhenDirty.
  • Whenever possible prefer to use the OnActivated, OnDeactivated or OnDataSourceChanged callbacks instead of the Update callback.

DataBinding

  • Be sure to set the appropriate bindingMode for your use case. For example, when changes in the UI should not be replicated in the source or if the UI is readonly, set the bindingMode to BindingMode.ToTarget to avoid data corruption.

Data Sources

  • Prefer to use C# properties instead of fields when defining a bindable property. This will give a chance to do validation, notify of changes when using versioning, etc.
  • Avoid creating C# properties that do a lot of work. If necessary, do the work as required and use a cached value for the bindings.
  • Avoid notifying changes where no change happened (i.e. not checking if the value actually changed before sending the notification).
  • Prefer to use versioning when creating a data source. For maximum performance, use both versioning features together.
  • As much as possible, prefer to write data sources that will act as a buffer between your data and the UI rather than using the data directly.
    • This will make it easier to control the flow of the data and be aware of the changes coming from the UI. This will also allow to control when the data is updated.
    • This will make it easier to keep all UI data in one spot and keep paths as short as possible.
    • This will allow you to keep the original data as lean and clean (no need to instrument your types, etc.)
    • This will allow you to prepare the data for UI (i.e. manually converting the data in your code will be faster than defining and setting conversion methods on binding objects).

Type Conversion

  • Although it is unavoidable in some cases (i.e. anything dealing with Enum), avoid writing conversion delegates that allocate memory.
  • Avoid doing any lengthy work in a converter.
  • Prefer to bake in the type conversion in your data source than relying on per-binding conversions.

Custom Elements

  • When implementing a custom field, avoid using bindings to update the internal data of the control (i.e. a Vector3Field should not use bindings to keep the x, y and z sub-elements in sync).
  • Avoid creating C# properties that do a lot of work. If necessary, do the work as required and use a cached value for the bindings.
  • Avoid notifying changes where no change happened (i.e. not checking if the value actually changed before sending the notification).

Property Paths

  • Prefer to use shorter data source paths whenever possible. This is unavoidable, the longer the path, the more work we need to do to extract or set a value.
    • Note that while we will internally cache the resolved paths, we will still combine all relative paths.
  • Avoid creating property paths that have more than four parts, as it will allocate memory for the additional parts.
  • Prefer to construct complex paths by combining parts instead of creating a Unity.Properties.PropertyPath with a string.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment