Skip to content

Attributes

orels1 edited this page Jul 24, 2020 · 27 revisions

A collection of attributes to create custom UIs for your own behaviours

Class Attributes

The following attributes are only available to use with classes. Make sure to always inherit from UTController base class or they will not do anything.

CustomName

[CustomName(string name)]

Sets a custom name shown in the controller's header bar.
Shows <NameOfControllerClass> with Controller part stripped by default, e.g. MyBehaviourController would be shown as MyBehaviour by default

[CustomName("My Fancy Controller")]
public class MyBehaviourController : UTController {}


HelpMessage

[HelpMessage(string message)]

Displays a box with some text below the controller's header bar and above the rest of the UI.
Usually used to describe the purpose of the behaviour if it is not obvious, or to warn user about anything in particular.

[HelpMessage("This behaviour should be enabled at all times")]
public class MyBehaviourController : UTController {}


ControlledBehaviour

[ControlledBehaviour(Type udonSharpBehaviour)]

Automatically adds an UdonBehaviour of the specified type to the game object if no Udon Behaviour component is provided. Makes the setup easier for the end user, allowing them to just add the Controller which will take care of everything else.

[ControlledBehaviour(typeof(MyBehaviour))]
public class MyBehaviourController : UTController {}

Note: this works by searching through UdonSharpProgramAssets to find the corresponding class. Make sure to create the program asset and the class before adding this attribute.

Field Attributes

These attributes are meant to go on public fields of your Controller. They serve as UI buiding blocks and provide an ability to react to value changes, for example if you would like to do something specific in the scene when user checks a checkbox.

Note: these attributes use a property modifier approach, as unity doesn't allow to stack multiple property drawers otherwise. Make sure to use them in combination with a [UTEditor] or an [UdonPublic] attribute or they will not do anything. Both of those should go last in the chain, right before the public keyword.

Many of them can be combined together to form more elaborate UI systems, so something like this is completely normal

[OnValueChanged("HandleChange"]
[HelpBox("Value cannot be negative", "CheckValueValidity")]
[HideIf("@!transition")]
[HideLabel] [UdonPublic]
public float duration;

Common Parameters

Some attributes share parameter names. One of such parameters is methodName. In most cases you will be able to pass either a method or a variable name to it (where it makes sense, there are exceptions and they are mentioned separately).

// Will execute `ShouldShowBox` to determine whether the box should be visible
[HelpBox("", "ShouldShowBox")] [UdonPublic];
public bool active;

// Must return `bool`
public bool ShouldShowBox() {
  return active;
}

To use a variable instead of a method - prefix the variable name with @, you can also invert the variable value by adding ! after that.

// Will show if active is `true`
[HelpBox("", "@active")] [UdonPublic];
public bool active;

// Will show if active is `false`
[HelpBox("", "@!active")] [UdonPublic];
public bool active;

This can be any public variable of a class, doesn't have to be specifically the same variable. You can use something like [HideInInspector] for storing the state of the box without displaying it in the editor.

SectionHeader

[SectionHeader(string title)]

Displays a visual separator box with some text

[SectionHeader("General")][UdonPublic]
public Transform sourceTransform;


HelpBox

[HelpBox(string message, [string methodName])]

Displays a box with a help message. You can conditionally hide and show the box based on a method or variable. See Common Parameters for more info.

// Always visible
[HelpBox("This option disables rotation transfer")]
[UdonPublic]
public bool ignoreRotation;

// Only visible if provided variable is set to `true`
[HelpBox("This option disables rotation transfer", "@ignoreRotation")]
[UdonPublic]
public bool ignoreRotation;

// Only visible if provided variable is set to `false`
[HelpBox("This option disables rotation transfer", "@!ignoreRotation")]
[UdonPublic]
public bool ignoreRotation;

// Only visible if the provided method returns `true`
[HelpBox("This option disables rotation transfer", "ShowIgnoreHelp")]
[UdonPublic]
public bool ignoreRotation;

public bool ShowIgnoreHelp() {
  return ignoreRotation;
}


HideIf

[HideIf(string methodName)]

Hides the field based on the provided method or variable. See Common Parameters for more info.

public bool enableEffects = true;

// Hides the field if `enableEffects` is unchecked
[HideIf("@!enableEffects")]
[UdonPublic]
public float effectsDuration;

public bool skipTransition;

// Hides the field if `skipTransition` is checked
[HideIf("This option disables rotation transfer", "@skipTransition")]
[UdonPublic]
public float transitionDuration;

// Hides the fields if the provided method returns true
public bool enableEffects;
public float effectsDuration;

[HideIf("HideExtras")]
[UdonPublic]
public bool extraOption1;

[HideIf("HideExtras")]
[UdonPublic]
public bool extraOption2;

public bool HideExtras() {
  return enableEffects && effectsDuration > 0;
}

HideLabel

[HideLabel]

Simply hides the field label and draws the value field only. Helpful in combinations with things like Horizontal attribute

// Will show the checkbox only
[HideLabel] [UdonPublic]
public bool active;

OnValueChanged

[OnValueChanged(string methodName)]

Calls provided method when the value of the variable changes so you can react to it in the UI.
Has some special behaviour when used together with ListView.

For regular fields the method signature should look like public void MethodName(object value)

// Will call the provided method with the fresh value every time it changes
[OnValueChanged("ToggleLights")] [UdonPublic]
public bool lightsActive;

// Incoming value will be the new value, while the current variable will not be updated yet.
// This allows you to compare old and new values.
public void ToggleLights(object value) {
  // cast to the expected type first
  var val = (bool) value;
  if (value) {
    // do something here
  } else {
    // do something here
  }
}

For array type fields the method signature is public void MethodName(object value, int index)

[OnValueChanged("HandleArrayChange")] [UdonPublic]
public string[] namesList;

public void HandleArrayChange(object value, int index) {
  // if value is `null` - the value at `index` was removed
  if (value == null) {
    // handle removal
    return;
  }
  // if `index` is out of range of the current array - a new value was added
  if (index == namesList.length) {
    // handle addition of new value
    return;
  }
  // handle change of an existing value
}

When used with ListView the method signature should be different: public void MethodName(object lValue, object rValue, int index), where lValue and rValue represent the left and right variable of the list view at the changed index.

You only need to attach [OnValueChanged] to the first instante of a particular ListView.

[OnValueChanged("HandleChange")
[ListView("Events List")][UdonPublic]
public UdonBehaviour[] udonTargets;

[ListView("Events List")][UdonPublic]
public string[] udonEvents;

// Handle a change of row values
public void HandleChange(object lValue, object rValue, int index) {
  // when the value is removed - both will be null
  if (lValue == null && rValue == null) {
    // handle the removal of a row at `index` here
    return;
  }
  // when the value is added - `index` will be out of range of the current list
  if (index == udonTargets.Length) {
    // handle addition of new row
    return;
  }
  var lCasted = (UdonBehaviour) lValue;
  var rCasted = (string) rValue;
  // handle change of an existing values
}

Horizontal

[Horizontal(string groupName)]

Combines two fields into a horizontal group based on the provided name.
You can define variables in any order, they can even have other variables between them. The fetching is done purely by the group name.

// Only 2 variables per group are supported at this time
[Horizontal("Group")] [UdonPublic]
public GameObject varA;

[Horizontal("Group")] [UdonPublic]
public string varB;

// You can have many groups in a controller
[Horizontal("OtherGroup")] [Udon Public]
public int varC;

[Horizontal("OtherGroup")] [Udon Public]
public int varD;


ListView

RangeSlider

Popup

Toggle

UdonPublic

UTEditor

Method Attributes

Button

Clone this wiki locally