OneClicks Overview

OneClicks are the equivalent of presets for different (supported) model types. All OneClicks generally operate the same way and produce similar results (as much as is possible considering the differences between model/character systems). The application of a OneClick on a supported model will configure:

  1. A SALSA module with visemes corresponding to our current recommendations.
  2. One EmoteR instance with SALSA-linked emphasis emotes.
  3. An Eyes module with head, eyes, and eyelids configurations.

Using a OneClick should be considered a starting point for setting up a character model. We have spent a lot of time testing different settings and configurations and have come up with a current setup that we believe creates a great look-and-feel. Please feel free to tweak and adjust any aspect that better suits your needs.

For a quick overview of how OneClicks are applied to character models, please see Part 4 (OneClicks), of our video tutorial series.

Available OneClick Options

OneClicks are only available for specific 3D character model systems as indicated below. However, nearly any model that uses blendshapes or bones (or both) for animation may be configured to work with SALSA LipSync Suite v2.

OneClick Installation

  • Make sure SALSA LipSync Suite is installed.
  • If upgrading from previously-installed OneClicks prior to v2.1.0, first remove the existing OneClick directory located here:
    Assets > Plugins > Crazy Minnow Studio > SALSA LipSync > Editor > OneClicks
  • Download and install the latest OneClick Base (REQUIRED for all OneClicks). Also ensure the appropriate version of the SALSA Suite is installed. Release notes for OneClickBase are located in the script itself.
  • Download the appropriate model-specific OneClick unitypackage and install it. Release notes for all OneClicks are located in the OneClick Editor scripts.

NOTE: Installation of unitypackage files is quite simple. If you are new to the process, please see this page.

Applying the OneClick

  • Select the model's root in your scene.
  • Apply the OneClick -- GameObject menu: Crazy Minnow Studio > SALSA LipSync > One-Clicks
  • Hit 'Play'.

NOTE: If you installed the core examples, the included Promo-male audio clip will be assigned -- otherwise, add an AudioClip of your choice to the SALSA-linked AudioSource.

Currently Available OneClicks

(Mixamo) Fuse

Special instructions: Adobe models may not work due to inconsistent mesh/shape naming.

Reallusion CC3 and iClone

Special instructions: Reallusion is a very flexible system with varying ways to import and export models. Generally speaking, if you are specifically using iClone models, use the iClone OneClick. For most other instances, use the CC3 OneClick. As new updates or use-cases evolve, we will assess the situation and attempt to update the OneClick to support models generated from the system when we are made aware and when possible or warranted.

Current supported situations: Standard/Game iClone/CC3 exported models should work. DAZ models imported with 3DExchange system and leveraging the CC3 animation system should work with the CC3 OneClick.

If you choose to create animations using blendshapes within the iClone/CC3 system, exported animations will interfere with SALSA, EmoteR, and Eyes. There are currently three options available to deal with this situation:

  1. Do not export animations using blendshapes -- use the SALSA Suite to handle your character's facial animations.

  2. Only use animations with blendshapes not being used by SALSA, EmoteR, or Eyes. This will require editing the animation and removing the conflicting blendshapes.

  3. Try the experimental SALSA setting, enabling persistence mode. Also, Enable persistence on all conflicting emotes. Persistence does add overhead to the SALSA Suite; however, it may be negligible in most situations.

DAZ3D (for Genesis models)

Special instructions: NONE

Autodesk Character Generator (ACG)

Special instructions:
Autodesk supports level-of-detail (LOD) meshes on export. We are aware of four levels of detail and have built that into a helper script that provides an interface to switching these levels and subsequently switching out the SALSA, EmoteR, and Eyes configurations to work with each level. This functionality can occur at runtime, on-the-fly.

NOTE: Support for run-time LOD switching requires SALSA LipSync Suite version 2.0.1+

LOD functionality is built into the OneClick applied to the model. In most OneClicks, the configuration application is simply called and the SALSA Suite modules are added to the model and automatically configured. Autodesk gets an additional component added to the model which provides LOD functionality.

LOD Functionality

The following general rules of functionality are available to supported Autodesk models.

  1. Applying the OneClick to a model automatically applies SALSA, EmoteR, and Eyes and sets the model's highest level of detail as active.

  2. Specifying an LOD that does not exist results in an attempt to apply the next highest LOD until one is found. If the attempt exceeds the available levels for Autodesk (3 -- the fourth level: high), the operation is aborted and no levels are activated.

  3. Specifying an LOD increase [IncreaseLOD()] attempts to increase the LOD detail by one level. If the next level is not available, the process is repeated until a valid level is found. If no valid level is found, the process aborts.

  4. Specifying an LOD decrease [DecreaseLOD()] attempts to decrease the LOD detail by one level. If the next leve is not available, the process is repeated until a valid level is found. If no valid level is found, the process aborts.

  5. Autodesk utilizes up to 4 levels of detail. The OneClick API treats these levels as zero-based [0..3]. If using the OneClick API to change levels of detail at run-time, specify the LOD as an integer between [0..3] and understand the rules above.

    • 0 = crowd (lowest level)
    • 1 = low
    • 2 = mid
    • 3 = high (highest level)

ACG API Information

namespace CrazyMinnow.SALSA.OneClicks

class OneClickAutodeskCGLod(){}

public bool SetLOD(int lodLevel)

Set a specific LOD based on [0..3] available LODs. Note the rules in LOD Functionality above. Returns true when successful and false when an available LOD is not found.

public int GetMaxLod()

Returns the highest LOD available based on [0..3] indexing. See LOD Functionality.

public bool IncreaseLOD()

Increases the level of detail based on the rules in LOD Functionality above. Returns true when successful and false when an available LOD is not found.

NOTE: A helper method is available that allows easy link-up to UGUI button functionality. It does not include the bool return value.
public void Increase()

public bool DecreaseLOD()

Decreases the level of detail based on the rules in LOD Functionality above. Returns true when successful and false when an available LOD is not found.

NOTE: A helper method is available that allows easy link-up to UGUI button functionality. It does not include the bool return value.
public void Decrease()


Special instructions:

NOTE: OneClickUmaDcs requires SALSA LipSync Suite v2.1.0+ and OneClickBase v2.1.5+

Since UMA is a run-time character system with many options, our setup scripts are slightly different than our other one-clicks and meant primarily to demonstrate what is possible when using the SALSA LipSync Suite with the UMA system. The SALSA Suite leverages the UMA Expression Player system for implementing the OneClick functionality. Using this system, it is easy to also leverage design-time preview mode, making it much more approachable to add/modify ExpressionComponents. It is; however, also possible to use UMA using Bone controller types if you prefer -- however, this would required the designer to implement this option manually.

We have developed a special controller type for use in SALSA Suite components: UMA. This controller type adds a proxy component (UmaUepProxy) to the GameObject that allows the core system to communicate with the UMA OneClick without the requirement of dealing with the dependencies of the UMA system in the core SALSA LipSync Suite. The OneClick for UMA also requires a "driver" component (UmaUepDriver), which is included in the OneClick package for UMA. This driver is the middleware to the UMA system -- it does have a dependency on the UMA package and will generate errors if it is imported into your project without UMA already being present. Once UMA is imported all errors should disappear.

NOTE: If re-configuring an UMA avatar at runtime, please also see the Runtime Setup documentation and in particular, the UMA Considerations portion of that document.

Applying UMA OneClick

OneClickUmaDcs can be applied to any GameObject; however, for correct one-click operation, ensure you apply it to the root object where the UMA avatar is configured. We use the "Getting Started" option to setup an UMA character, leveraging the prefabs for UMA_DCS and UMADynamicCharacterAvatar in-scene.

The OneClick is applied to the UMADynamicCharacterAvatar in-scene.

UMA Preview Mode

SALSA LipSync Suite leverages the avatars used in the UMA Core Tool - Expression Clip Editor (In the Examples folder) for preview. Therefore, for preview mode to work, the UMA / Examples / Expressions Examples folder must be present in your project. Once you have configured your avatar and no further configuration is required, you may remove this folder if desired. You may also remove the prefabs in the Crazy Minnow Studio / Addons / OneClickUMA folder.

NOTE: for preview operation, the UmaUepDriver component must be open in your GameObject's Inspector window.

UMA Selective Eyes Module Implementation (Eye/Head)

If you wish to use your own Head or Eye animation method, you may do so by disabling the options in the UmaUepDriver component (in the Inspector). Simply uncheck the appropriate checkbox. We recommend using these options, but you are free to disable them if you wish.

UMA Setup - Manual Mode

It is also possible to use the UMA OneClick with other manual UMA-based setups. If you are setting your character up differently from the UMA GettingStarted method, it is likely the OneClick will work with it providing you adhere to a few caveats.

  1. OneClick requires UMAExpressionPlayer.
  2. You will need to configure the UMAExpressionPlayer yourself.
  3. You will need to call our driver to initialize the process.

To implement a OneClick UMA setup without using the GettingStarted prefab method:

  • Same as previous, apply the OneClick to your avatar root.
  • On the UmaUepDriver, disable (uncheck) the "UMA Character is Dynamic" option.
  • Configure an UMAExpressionPlayer on your avatar and you will need to configure it with these parameters: UMAExpressionPlayer.expressionSet = yourExpressionSet;
    UMAExpressionPlayer.umaData = yourUmaData;
  • Finally, programmatically call our UEP driver manual start function, passing a link to the UMAExpressionPlayer you just configured:

Creating a Custom OneClick

This is a relatively easy process currently applicable to SALSA and/or EmoteR settings changes. There are generally 3 files associated with a OneClick (not counting the OneClickBase, which is required for all OneClicks). The ACG OneClick has an extra file for LOD information and switching. And UMA is quite a different beast altogether.

The 3 common files consist of:

  • An Editor script which allows you to apply a OneClick from the Editor GameObject menu.
  • A runtime script for SALSA and EmoteR settings.
  • A runtime script for the Eyes module configuration.

1. Duplicate the Provided OneClick Scripts

For this example, we will use the CC3 set of scripts.

  • Duplicate (ctrl-D) the exiting CC3 OneClick Editor file.
    duplicate editor file
  • And give it a unique name (i.e. MyCustomOneClickEditor).
    rename editor file
  • Change the Class name of your custom OneClickEditor script to match the file name and give the menu item a unique name.
    change class menu name
  • Perform the same operations to duplicate the SALSA/EmoteR OneClick script, give it a unique name (MyCustomOneClick), and change the Class name to match the file name.
  • Perform the same operations to duplicate the Eyes OneClick script, give it a unique name (MyCustomOneClickEyes), and change the Class name to match the file name.
    duplicate runtime files
  • Open the custom OneClickEditor file again and link it to the new SALSA/EmoteR and Eyes scripts in the ApplyOneClick() method.
    edit editor file

2. Modify Existing OneClick Settings

Adjust any settings in the new custom OneClick runtimes for SALSA/EmoteR and Eyes.

To adjust existing settings for SALSA or EmoteR, it is pretty easy to simply look at the MyCustomOneClick.cs file (SALSA/EmoteR config) and add, remove, or change settings to your liking. Just change the values, names, etc. to your preference. For example, looking at the CC3 OneClick file we copied, in the SALSA configuration section, we have a relatively easy configuration to work with.

2.1. Modifying SALSA Viseme Definitions

First, locate the definition of a new viseme expression named "w", followed by a bone ExpressionComponent definition, followed by a shape ExpressionComponent definition. Bare in mind, these definitions are simplified into the OneClickBase configuration command "language".

    new TformBase(new Vector3(-0.08919834f, 0.02136874f, 6.878996E-05f),
    new Quaternion(0.9989499f, -0.04581843f, 5.542967E-07f, 2.483174E-07f),
    new Vector3(1f, 1f, 1f)),
    0.08f, 0f, 0.06f,
    false, true, false);
AddShapeComponent(new []{"^Mouth_Lips_Open.*$"}, 0.08f, 0f, 0.06f, "Mouth_Lips_Open", 0.378f, true);


The new viseme expression command is easy enough to understand, call the NewExpression() method, passing a string parameter containing the new viseme name.


Any additional component definitions following the NewExpression() command are applied to this Expression (viseme or emote). Therefore, issue the NewExpression() command and then add 'bone' or 'shape' component definitions, then signify a new viseme or emote with another NewExpression() command, followed by more component definitions, etc.


Since it is a bit simpler, let's first examine a shape component definition. The command AddShapeComponent() defines the minimal requirements for a new shape component:

AddShapeComponent(new []{"^Mouth_Lips_Open.*$"}, 0.08f, 0f, 0.06f, "Mouth_Lips_Open", 0.378f, true);
  • First we pass an array of search strings (one or more) consisting of possible shape names. This example is using the CC3 OneClick as a model and has a single search string in simple regex format. In some OneClicks there are multiple shape names to look for depending on the generation of model or the options chosen at export. Therefore, you may see a more complex parameter in the OneClick you are copying/adjusting or it may simply be a single string literal or regex. For example, here is a search array from the DAZ OneClick: new[] {"head__eCTRLvW", "head__VSMW", "head__CTRLVSMW"}. When executing, OneClickBase will sequentially look for a blendshape match in the order provided. It will stop looking after the first success. NOTE: The search type used for these strings is either string literal or regex (.net). See information below (last parameter - bool value) for signifying (to OneClickBase) which is used.
  • The next 3 parameters (0.08f, 0f, 0.06f) are the animation timings (ON/Hold/OFF). NOTE: as per the SALSA documentation, the "Hold" value is not used by SALSA. This value is arbitrary and can be any float value.
  • The string parameter ("Mouth_Lips_Open") is the name that will be assigned to the new component.
  • Next is the blendshape amount for the "max" position (animate ON). NOTE this value is passed as "normalized" value of the blendshape. In this case, 0.378f would equate to a blendshape value of 37.8f when set in the SkinnedMeshRenderer. Also note, this is no longer a clamped [0f .. 1f] value and does support the over/under-driving capabilities in Unity 2018.3+. It is still necessary to represent the value as a 'fractional' value to support the SALSA Core internals and provide backwards compatibility. Therefore, simply use values that derive from the SkinnedMeshRenderer blendshape values divided by 100. i.e. (-32.5f = -0.325f) and (126.2f = 1.262f).
  • Finally, an optional boolean parameter, which defines the search type: simple string literal (false: default) or regex (true).


Adding a bone component is a little more involved since it is a slightly more complex controller type:

    new TformBase(new Vector3(-0.08919834f, 0.02136874f, 6.878996E-05f),
    new Quaternion(0.9989499f, -0.04581843f, 5.542967E-07f, 2.483174E-07f),
    new Vector3(1f, 1f, 1f)),
    0.08f, 0f, 0.06f,
    false, true, false);
  • The first parameter is the regex search (from the context of the root/parent) for the bone GameObject, in this case "CC_Base_Teeth02".
  • The next three values are the "max" setting for the position (TformBase), rotation (Quaternion), and scale (Vector3). This is where the bone will animate towards when the animation is turned ON.
  • The next three values (0.08f, 0f, 0.06f) are the animation timings (ON/Hold/OFF).
  • The string value "CC_Base_Teeth02" is the name assigned to the component.
  • Finally, the three booleans apply to the constraints on the bone transform (position, rotation, scale). In this case, we are applying the "max" settings configured in the TformBase, Quaternion, and Vector3 parameters above, restricting the bone to rotational changes. Position (TformBase) is false, Rotation (Quaternion) is true, and scale (Vector3) is false. SALSA will only apply rotational animation to the transform of this bone.

2.2. Modifying EmoteR Emote Definitions

Emotes are defined nearly identically to SALSA visemes with one small addition, the additional configuration call to set the EmoteR specialty pool flags as noted in the example below. This configuration creates an emote named "browsUp" and looks for 4 different blendshapes to create shape components with.

AddEmoteFlags(false, true, false, 1f);
AddShapeComponent(new []{"^Brow_Raise_L.*$"}, 0.2f, 0.1f, 0.15f, "Brow_Raise_L", 0.907f, true);
AddShapeComponent(new []{"^Brow_Raise_R.*$"}, 0.25f, 0.2f, 0.1f, "Brow_Raise_R", 0.72f, true);
AddShapeComponent(new []{"^Brow_Raise_Inner_R.*$"}, 0.25f, 0.2f, 0.15f, "Brow_Raise_Inner_R", 0.68f, true);
AddShapeComponent(new []{"^Brow_Raise_Inner_L.*$"}, 0.2f, 0.08f, 0.15f, "Brow_Raise_Inner_L", 0.687f, true);

Creating a new emote definition is nearly identical to a SALSA viseme, first use the NewExpression() command with the string name as a parameter. See the SALSA information above for more detail.


Here's the real difference between an emote and viseme definition. An Emote can be a member of up to 3 specialty pools and we define the specialty pool flags with the AddEmoteFlags() command:

AddEmoteFlags(false, true, false, 1f);
  • Three bools for 3 pools: random pool, lipsync emphasis pool, and repeater pool. Pass true for inclusion and false for exclusion in the respective pool.
  • Additionally, there is an float value passed that indicates the overall emote's Expression Dynamics or fractional variation value.


Other than the specialty pool command, an emote definition is pretty much identical to a viseme definition using the OneClickBase command language. Define one or more bone and/or shape ExpressionComponents in the same way as a SALSA viseme.

3. Adding New Settings or Overriding Defaults

The command language is not all-inclusive of the available settings and is designed (currently) as a minimal configuration utility. There are many more options available to configure global SALSA and EmoteR settings, individual viseme and emote settings, and even component-level settings per viseme or emote.

To add new settings for SALSA or EmoteR, we recommend adding any special code below the DoOneClickiness() method call (in file MyCustomOneClick.cs). DoOneClickiness() is the final call in the SALSA/EmoteR script that initiates the creation of the SALSA and EmoteR configuration once it has been defined. Therefore, it is advised to place your additional settings-configuration code below this call to prevent them from potentially being overwritten by DoOneClickiness() or other default config values when DoOneClickiness() is invoked.

NOTE: See the SALSA API and/or the EmoteR API for information on available settings and options. See API usage with ExpressionComponents for more information on modifying ExpressionComponent settings.

For example:

DoOneClickiness(gameObject, clip);  // add/change configuration settings below this method call.

// EmoteR global settings
emoter.lipsyncEmphasisChance = 0.0f;
salsa.emphasizerTrigger = 0.0f;

// Change settings on a specific 'emote'...
var myemote = emoter.FindEmote("My New Emote Name");
myemote.isPersistent = true;
myemote.isRandomEmote = true;

// Change settings on the components of a specific 'emote'...
foreach (var component in myemote.expData.components)
    component.easing = LerpEasings.EasingType.Linear;

// Find a viseme in SALSA and change its components' settings...must exist or will error...
var myviseme = salsa.visemes[salsa.visemes.FindIndex(v => == "My New Viseme")];
foreach (var component in myviseme.expData.components)
    component.durationOn = 0.11f;
    component.easing = LerpEasings.EasingType.CircleIn;

// Change settings in all SALSA visemes...
foreach (var viseme in salsa.visemes)
    foreach (var component in viseme.expData.components)
        component.durationOff = 0.08f;