Parameter Manipulation in Cubism SDK for Unity
Updated: 01/31/2020
When manipulating the values of model parameters in Cubism SDK for Unity, it must be done at the timing from MonoBehaviour.LateUpdate() to MonoBehaviour.OnPreRender() in Unity’s event functions.
Click here for more information on the order of execution of Unity’s event functions.
The process of playing the AnimationClip takes place between the Unity event functions MonoBehaviour.Update() and MonoBehaviour.LateUpdate().
If the parameter value is manipulated with MonoBehaviour.Update(), it will be overwritten by the value of the AnimationClip that is played immediately after.
Therefore, any manipulation of parameter values should be done after AnimationClip has set the values.
All components included with Cubism SDK for Unity manipulate parameter values from MonoBehaviour.LateUpdate().
Also, since CubismModel.OnRenderObject() performs the model vertex update process from the parameter values at each frame, any value manipulation later than this will not be computed.
Note: CubismModel.OnRenderObject() is called when each Camera placed in a Scene finishes rendering. Therefore, if multiple Cameras are placed in a Scene, CubismModel.OnRenderObject() will be called as many times as the number of Cameras.
Operation in SRP
Unity added the “Scriptable Render Pipeline (SRP)” in 2018.1, a mechanism that allows C# scripts to control rendering settings and execution.
See the official Unity documentation for more information on SRP.
When using this render pipeline, some Unity event functions are not called.
In Cubism SDK for Unity, CubismModel.OnRenderObject() is used to update the model vertices from the set parameter values.
This is because the vertex update process is called after LateUpdate(), which is updating parameter values, but MonoBehaviour.OnRenderObject() is not called in the SRP project.
In Cubism SDK for Unity R1 or later, if the project is Unity 2018.1 or later with SRP support, the function that handles vertex updates is registered by PlayerLoop to be called after LateUpdate().
private bool WasAttachedModelUpdateFunction { get; set; } ... /// <summary> /// Called by Unity. Triggers <see langword="this"/> to update. /// </summary> private void Update() { #if UNITY_2018_1_OR_NEWER if (!WasAttachedModelUpdateFunction) { _modelUpdateFunctions += OnModelUpdate; WasAttachedModelUpdateFunction = true; } #endif ... /// <summary> /// Called by Unity. Destroys instance. /// </summary> private void OnDisable() { #if UNITY_2018_1_OR_NEWER if (WasAttachedModelUpdateFunction) { _modelUpdateFunctions -= OnModelUpdate; WasAttachedModelUpdateFunction = false; } #endif } /// <summary> /// Called by Unity. Blockingly updates <see langword="this"/> on first frame enabled; otherwise tries async update. /// </summary> private void OnRenderObject() { #if !UNITY_2018_1_OR_NEWER OnModelUpdate(); #endif } ... /// <summary> /// Update model states. /// </summary> private void OnModelUpdate() { // Vertex update process }