Skip to main content

Expose Parameters to the Remote App with LiveProperty

warning

Many features are still experimental and breaking changes may occur.

Attaching attributes such as [LiveClass] / [LiveField] / [LiveProperty] to a Studio-app-side script in VirgoMotionStudioTemplate turns that member into a LiveProperty. LiveProperties are used consistently for the following purposes:

  • Editing values and calling functions from the Remote App
  • Saving to and restoring from a live scene (*.live.json)
  • Recording to and playback from live data (*.live.bin)
Migrating from the old Exposed* attributes

In RemoteControl 0.26.0, the Exposed* attributes such as [ExposedClass] were renamed to Live*. See Migrating from the Old Names for the mapping.

Minimal Example​

1. Write a Script​

Attach [LiveClass] and [LiveField] to a MonoBehaviour.

using UnityEngine;
using Lilium.RemoteControl;

[LiveClass]
public class MyEffect : MonoBehaviour
{
[LiveField]
public int hoge;
}

2. Add a GameObject and Attach the Script​

Create an empty GameObject in the Studio scene of VirgoMotionStudioTemplate and attach the script above.

alt text

3. Register It with the Remote Control Container​

Select the Remote Control Container GameObject already placed in the scene, and add an entry to the Objects list of the Remote Control Container component.

  1. Press the + button on Objects, then select LiveGameObject from the type dropdown
  2. Drag the GameObject created in step 2 into the Reference field of that entry

The Id is assigned automatically when you add the entry. Values restored from a live scene are matched to this Id, so avoid changing it later.

Simply attaching [LiveClass] will not make it appear on the Remote App's "Live Scene" page. The [LiveClass] components attached to the GameObjects registered in Objects are exposed together.

tip

If you also want to control position, rotation, and scale from the Remote App, choose LiveGameObjectWithTransform instead of LiveGameObject.

4. Verify the Behavior​

Press Play in the Unity Editor, or launch the built app and connect from the Remote App. MyEffect will appear on the Remote App's "Live Scene" page, and the hoge field will be shown as an integer input. Changing the value is reflected immediately, and saving the live scene writes it to *.live.json.

alt text

tip

You don't need to press Play — starting the server via the toggle in the editor toolbar (the devices icon) lets you connect from the Remote App while staying in Edit mode.

note

The [LiveField] and other attributes you add may not be recognized correctly on the Remote App side. In that case, stop Play mode, then press the Reset button in Window > Lilium Remote Control > UI Designer and re-enter Play mode.

alt text

Choosing Between Attributes​

AttributeTargetPurpose
[LiveClass]class / structRegisters this type as one that holds LiveProperties
[LiveField]fieldExposes a field and makes it editable
[LiveProperty]propertyExposes a property. Editable if it has a setter; read-only display if it only has a getter
[LiveFunction]methodExposes a method as a button
[LiveEnum]enumRequired to display enum values as a dropdown
[Help("...")]any of the aboveShows help text in the Remote App
[Hide]field / property / methodHides an already-exposed member from the Remote App UI

[LiveField] is sufficient in most cases. Use [LiveProperty] when you want to run logic when the value changes.

Running Logic on Value Change with LiveProperty​

When you write to a property with [LiveProperty] from the Remote App, its setter is called. Write logic in the setter to reflect the change in the scene immediately.

using UnityEngine;
using Lilium.RemoteControl;

[LiveClass]
public class MyLight : MonoBehaviour, ILiveDeserializeCallback
{
[SerializeField]
private Light targetLight;

// The value that actually gets saved (shadow field)
[LiveField, Hide, FormerlyNamedAs("intensity")]
private float _intensity = 1f;

// The member shown to the Remote App
[LiveProperty, Slider(0f, 8f)]
public float intensity
{
get => _intensity;
set
{
_intensity = value;
targetLight.intensity = value; // logic run on change
}
}

// Called after the live scene finishes loading
public void OnAfterLiveDeserialize()
{
targetLight.intensity = _intensity;
}
}
  • [LiveProperty] alone is not saved to the live scene. To save it, pair it with a field marked [LiveField, Hide, FormerlyNamedAs("propertyName")]. This field is called a shadow field, and only the property side is shown in the Remote App.
  • Saving and restoring a live scene reads and writes the shadow field directly; the setter is not called. Put any logic that needs to run after loading in ILiveDeserializeCallback.OnAfterLiveDeserialize.
  • If the actual value lives on another component and the shadow field can go stale, update the shadow field right before saving in ILiveSerializeCallback.OnBeforeLiveSerialize.

Customize How Values Are Displayed​

Numeric sliders, labels, display order, and so on can be controlled via attributes.

using UnityEngine;
using Lilium.RemoteControl;

[LiveClass(Category = "Effect", Icon = "auto_fix_high")]
public class MyEffect : MonoBehaviour
{
[LiveField, Slider(0f, 1f, 0.01f)]
public float intensity = 0.5f;

[LiveField, Slider(1, 10)]
public int repeat = 3;

[LiveField]
public Color tint = Color.white;

[LiveFunction(label = "Reset")]
public void ResetParams()
{
intensity = 0.5f;
repeat = 3;
tint = Color.white;
}
}
SettingEffect
[Slider(min, max, step)]Displays a numeric value as a slider (omitting step defaults to 1/20 of the range)
[LiveClass(Category = "...")]The category heading on the "Live Scene" page
[LiveClass(Icon = "...")]Specifies a Material Icons icon name
labelDisplay name (e.g. [LiveField(label = "Strength")])
orderDisplay order (negative comes earlier, positive comes later)
[LiveFunction(icon = "...")]Icon shown on the button (Material Icons)

alt text

Expose enum Values as Choices​

For a field of an enum type, the enum itself must have [LiveEnum] attached.

using UnityEngine;
using Lilium.RemoteControl;

[LiveEnum]
public enum EffectMode
{
Off,
Soft,
Strong,
}

[LiveClass]
public class MyEffect : MonoBehaviour
{
[LiveField]
public EffectMode mode = EffectMode.Soft;
}

alt text

For enums you can't attach an attribute to, such as HumanBodyBones, register them with the assembly attribute [LiveExternalEnum].

[assembly: Lilium.RemoteControl.LiveExternalEnum(typeof(UnityEngine.HumanBodyBones), excludeNames = new[] { "LastBone" })]

Conditional Display​

ShowIf / HideIf let you control visibility based on the value of another field. When you attach more than one, the member is shown only when all conditions are met. They can also be attached to [LiveFunction] buttons.

[LiveField]
public bool useColor;

[LiveField, ShowIf(nameof(useColor), true)]
public Color color = Color.white;

Choosing Where a Value Is Saved​

By default, LiveProperty values are saved to the live scene (*.live.json).

SettingWhere it's saved
(none)The live scene (*.live.json)
[LiveField(persistable = false)]Not saved (still exposed to the Remote App)
[LiveField(persistScope = PersistScope.Project)]A project-wide settings file ({ClassName}.settings.json)

Use persistable = false for temporary, experimental values or values you want reset on every launch. Use PersistScope.Project for settings that don't change when you switch scenes, such as a port number.

Members saved to the live scene are also eligible for recording in live data. Members that aren't saved, or that are saved to project settings, are not recorded.

note

Adding, type-changing, or renaming exposed members can break compatibility with previously saved *.live.json files. When renaming, attach [FormerlyNamedAs("oldName")] so values saved under the old name can still be restored. It can also be used when renaming a class.

Exposing Values Without Changing a Script (LiveClassAsset)​

Classes you can't attach attributes to — Unity's built-in components, third-party components, and the like — can be exposed with a Live Class Asset.

  1. Open Window > Lilium Remote Control > Live Class Asset
  2. Assign a Live Class Asset to Preset (use New to create one)
  3. In the class list, use + (search across all classes) or From Selected (choose from the components on the currently selected GameObject) to add a class
  4. In the detail pane on the right, use + to check the properties, fields, and methods you want to expose. Labels and controls (such as sliders) are also configured here
  5. Apply the asset. To apply it project-wide, add it to the list in Project Settings > Lilium Remote Control; to carry it around with a scene or set, add it to the Assets list of a Remote Control Container

Register the GameObject that holds the component you want to expose in the Remote Control Container's Objects, the same as in step 3. For detailed steps, see Expose Any Property with a LiveClassAsset.

Migrating from the Old Names​

In RemoteControl 0.26.0, every "Exposed" name was renamed to "Live".

OldNew
[ExposedClass][LiveClass]
[ExposedField][LiveField]
[ExposedProperty][LiveProperty]
[ExposedFunction][LiveFunction]
[ExposedEnum][LiveEnum]
[ExposedExternalEnum][LiveExternalEnum]
[ExposedKey][LiveKey]
[ExposedDefault][LiveDefault]
[ExposedHelp("...")][Help("...")]
[FormerlyExposedAs("...")][FormerlyNamedAs("...")]
ExposedGameObject / ExposedGameObjectWithTransformLiveGameObject / LiveGameObjectWithTransform
OnExposedChanged / OnExposedResetOnLiveChanged / OnLiveReset
  • Entries already registered in a Remote Control Container and elsewhere are loaded automatically under the new type names.