MouthMovement (Cocos Creator)

最終更新: 2023年3月14日

概述

MouthMovement是针对口形同步参数的当前值,应用开/关状态值的功能。
可以将动态中设置的口形同步曲线和从正在播放的音频中实时采样的值等应用到模型中。
参考此处了解如何在模型上设置口形同步参数。

MouthMovement中唯一设置的是嘴巴的开合状态。
无法执行将嘴形与元音匹配等操作。

如果要在Cocos Creator上指定口形同步的参数,可以在Cubism Editor中的模型进行设置,也可以在Cocos Creator上由用户任意指定。

Cubism SDK for Cocos Creator中的MouthMovement包含三种类型的元素。

  1. 参数指定用组件
  2. 将值应用于各参数的组件
  3. 操作2中应用的值

1. 参数指定用组件

使用CubismMouthParameter指定要用于MouthMovement的参数。

CubismMouthParameter是一个继承Component的组件,
它通过附加到置入[Prefab根]/Parameters/下的Node来使用。
这会将与附加的Node具有相同ID的参数视为口形同步的参数。

如果模型本身设置有口形同步参数,那么CubismMouthParameter将在载入时附加到该参数的Node上。

由于CubismMouthParameter用作获取参考目的地的标记,因此它内部不处理任何内容,也没有数据。

2. 将值应用于各参数的组件

使用CubismMouthController将打开/关闭值应用于各参数。
这是一个继承自Component的组件,使用时会附加到Cubism的Prefab的根。

在原始化期间获取附加到Prefab的所有CubismMouthParameter的参考。
如果在执行过程中追加/删除眨眼参数,调用CubismMouthController.refresh()再次获取参考。

  public refresh() {
    const model = CoreComponentExtensionMethods.findCubismModel(this);

    // Fail silently...
    if (model == null || model.parameters == null) {
      return;
    }

    // Cache destinations.
    const tags = ComponentExtensionMethods.getComponentsMany(
      model.parameters,
      CubismMouthParameter
    );

    this.destinations = new Array(tags.length);

    for (let i = 0; i < tags.length; ++i) {
      this.destinations[i] = tags[i].getComponent(CubismParameter);
    }

    // Get cubism update controller.
    this.hasUpdateController = this.getComponent(CubismUpdateController) != null;
  }

...

  protected start() {
    // Initialize cache.
    this.refresh();
  }

CubismMouthController在每帧的lateUpdate()时机,将CubismMouthController.MouthOpening的值应用于CubismMouthParameter标记的参数。

  protected onLateUpdate(deltaTime: number) {
    // Fail silently.
    if (!this.enabled || this.destinations == null) {
      return;
    }

    // Apply value.
    CubismParameterExtensionMethods.blendToValueArray(
      this.destinations,
      this.blendMode,
      this.mouthOpening
    );
  }

MouthOpening的设置值在0.0f~1.0f的范围内。
CubismMouthController使用CubismMouthController.blendMode中设置的计算方法将此值应用于对象参数。

通过从外部操纵此MouthOpening值,您可以使模型的嘴巴张开或合上。

  @property({ type: CCFloat, slide: true, range: [0.0, 1.0, 0.01] })
  public mouthOpening: number = 1.0;

3. 操纵2中应用的值

如“2. 将值应用于各参数的组件”中所述,您可以通过操作CubismMouthController.mouthOpening的值,将值应用于口形同步的参数。

Cubism SDK for Cocos Creator可以通过以下三种方式操作此值:

  • 通过动态操纵值
  • 周期性操作值
  • 通过从AudioClip中采样来操作值

此外,通过在用户端实装对该值的操作处理,可以独立自定义口形同步速度、时间等。

Tips

如果操作CubismMouthController.mouthOpening的组件在CubismMouthController之后执行,它可能不会按预期动作。
如果动作出现问题,可以通过在用户端显式控制组件的执行顺序来避免。
在Cubism SDK for Cocos Creator中,各组件的执行顺序由CubismUpdateController控制,因此您也可以使用它。

此外,由于上述三种设置方法操作相同的值,很难在不作任何努力的情况下将它们共存于一个模型中。

通过动态操纵值

当使用设置有眨眼参数的模型通过Cubism的Animator创建动态时,可以设置眨眼曲线。

如果将带有眨眼曲线的.motion3.json载入Cocos Creator项目,Animation将以CubismMouthController.mouthOpening的值为对象生成该曲线。
因此,CubismMouthController.mouthOpening的值是通过以Animator组件等播放AnimationClip来操作的。

周期性操作值

使用CubismAutoMouthInput周期性操作口形同步的值。
CubismAutoMouthInput是一个使用正弦波计算和设置口形同步值的组件。

要使用CubismAutoMouthInput,请将其附加到Cubism的Prefab的根目录。

CubismAutoMouthInput有一个设置项目。

  • Timescale

    正弦波的周期发生变化。
  @property(CCFloat)
  public Timescale: number = 10.0;
  lateUpdate(deltaTime: number) {
    // Fail silently.
    if (this.Controller == null) {
      return;
    }

    // Progress time.
    this.T += deltaTime * this.Timescale;

    // Evaluate.
    this.Controller.mouthOpening = Math.abs(Math.sin(this.T));
  }

通过从音频中采样来操作值

使用CubismAudioMouthInput,从Cocos Creator上播放的音频中设置口形同步值。

CubismAudioMouthInput通过从AudioSource播放的音频信息中采样,实时生成和设置口形同步值。

要使用CubismAudioMouthInput,请将其附加到Cubism的Prefab的根目录。

  protected update(deltaTime: number) {
    const { audioInput, samples, target, sampleRate, gain, smoothing } = this;

    // 'Fail' silently.
    if (audioInput == null || target == null || samples == null || sampleRate == 0) {
      return;
    }
    const { trunc, sqrt } = Math;

    const { currentTime } = audioInput;
    const pos = trunc(currentTime * this.sampleRate);
    let length = 256;
    switch (this.samplingQuality) {
      case CubismAudioSamplingQuality.veryHigh:
        length = 256;
        break;
      case CubismAudioSamplingQuality.maximum:
        length = 512;
        break;
      default:
        length = 256;
        break;
    }

    // Sample audio.
    let total = 0.0;

    for (let i = 0; i < length; i++) {
      const sample = samples.getData((pos + i) % samples.length);
      total += sample * sample;
    }

    // Compute root mean square over samples.
    let rms = sqrt(total / length) * gain;

    // Clamp root mean square.
    rms = math.clamp01(rms);

    // Smooth rms.
    const output = MathExtensions.Float.smoothDamp(
      this.lastRms,
      rms,
      this.velocityBuffer,
      smoothing * 0.1,
      undefined,
      deltaTime
    );

    rms = output[0];
    this.velocityBuffer = output[1];

    // Set rms as mouth opening and store it for next evaluation.
    target.mouthOpening = rms;

    this.lastRms = rms;
  }

CubismAudioMouthInput有四个设置项目。

  @property(AudioSource)
  public audioInput: AudioSource | null = null;

  @property({ type: Enum(CubismAudioSamplingQuality) })
  public samplingQuality: CubismAudioSamplingQuality = CubismAudioSamplingQuality.high;

  @property({ type: CCFloat, slide: true, range: [1.0, 10.0, 0.01] })
  public gain: number = 1.0;

  @property({ type: CCFloat, slide: true, range: [0.0, 1.0, 0.01] })
  public smoothing: number = 0.0;
  • audioInput

    要采样的AudioSource的参考。
  • samplingQuality

    要采样的音频的精度。
  • gain

    采样值的倍率。

    1是同样大小,数值越大,口形同步值越大。
  • smoothing

    采样值的平滑化量。

    该值越高,口形同步值的变化就越平滑。
请问这篇文章对您有帮助吗?
关于本报道,敬请提出您的意见及要求。